| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.1 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Texture border clamp tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es31fTextureBorderClampTests.hpp" |
| |
| #include "glsTextureTestUtil.hpp" |
| |
| #include "tcuTextureUtil.hpp" |
| #include "tcuTexLookupVerifier.hpp" |
| #include "tcuTexCompareVerifier.hpp" |
| #include "tcuCompressedTexture.hpp" |
| #include "tcuResultCollector.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuSeedBuilder.hpp" |
| #include "tcuVectorUtil.hpp" |
| |
| #include "rrGenericVector.hpp" |
| |
| #include "gluContextInfo.hpp" |
| #include "gluTexture.hpp" |
| #include "gluTextureUtil.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "gluStrUtil.hpp" |
| #include "gluObjectWrapper.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "gluDrawUtil.hpp" |
| |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| |
| #include "deStringUtil.hpp" |
| #include "deUniquePtr.hpp" |
| #include "deRandom.hpp" |
| |
| #include <limits> |
| |
| namespace deqp |
| { |
| namespace gles31 |
| { |
| namespace Functional |
| { |
| namespace |
| { |
| |
| enum SizeType |
| { |
| SIZE_POT = 0, |
| SIZE_NPOT |
| }; |
| |
| bool filterRequiresFilterability(uint32_t filter) |
| { |
| switch (filter) |
| { |
| case GL_NEAREST: |
| case GL_NEAREST_MIPMAP_NEAREST: |
| return false; |
| |
| case GL_LINEAR: |
| case GL_LINEAR_MIPMAP_NEAREST: |
| case GL_NEAREST_MIPMAP_LINEAR: |
| case GL_LINEAR_MIPMAP_LINEAR: |
| return true; |
| |
| default: |
| DE_ASSERT(false); |
| return false; |
| } |
| } |
| |
| bool isDepthFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode) |
| { |
| if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) |
| { |
| // Unsized formats are a special case |
| return false; |
| } |
| else if (glu::isCompressedFormat(format)) |
| { |
| // no known compressed depth formats |
| return false; |
| } |
| else |
| { |
| const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); |
| |
| if (fmt.order == tcu::TextureFormat::D) |
| { |
| DE_ASSERT(mode == tcu::Sampler::MODE_DEPTH); |
| return true; |
| } |
| else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_DEPTH) |
| return true; |
| else |
| return false; |
| } |
| } |
| |
| bool isStencilFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode) |
| { |
| if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) |
| { |
| // Unsized formats are a special case |
| return false; |
| } |
| else if (glu::isCompressedFormat(format)) |
| { |
| // no known compressed stencil formats |
| return false; |
| } |
| else |
| { |
| const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); |
| |
| if (fmt.order == tcu::TextureFormat::S) |
| { |
| DE_ASSERT(mode == tcu::Sampler::MODE_STENCIL); |
| return true; |
| } |
| else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_STENCIL) |
| return true; |
| else |
| return false; |
| } |
| } |
| |
| tcu::TextureChannelClass getFormatChannelClass(uint32_t format, tcu::Sampler::DepthStencilMode mode) |
| { |
| if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) |
| { |
| // Unsized formats are a special c, use UNORM8 |
| return tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; |
| } |
| else if (glu::isCompressedFormat(format)) |
| { |
| const tcu::CompressedTexFormat compressedFmt = glu::mapGLCompressedTexFormat(format); |
| const tcu::TextureFormat uncompressedFmt = tcu::getUncompressedFormat(compressedFmt); |
| return tcu::getTextureChannelClass(uncompressedFmt.type); |
| } |
| else |
| { |
| const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); |
| const tcu::TextureFormat effectiveFmt = tcu::getEffectiveDepthStencilTextureFormat(fmt, mode); |
| |
| return tcu::getTextureChannelClass(effectiveFmt.type); |
| } |
| } |
| |
| int getDimensionNumBlocks(int dimensionSize, int blockSize) |
| { |
| // ceil( a / b ) |
| return (dimensionSize + blockSize - 1) / blockSize; |
| } |
| |
| void generateDummyCompressedData(tcu::CompressedTexture &dst, const tcu::CompressedTexFormat &format) |
| { |
| const int blockByteSize = tcu::getBlockSize(format); |
| const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(format); |
| const tcu::IVec3 numBlocks(getDimensionNumBlocks(dst.getWidth(), blockPixelSize.x()), |
| getDimensionNumBlocks(dst.getHeight(), blockPixelSize.y()), |
| getDimensionNumBlocks(dst.getDepth(), blockPixelSize.z())); |
| const int numTotalBlocks = numBlocks.x() * numBlocks.y() * numBlocks.z(); |
| const int dataSize = numTotalBlocks * blockByteSize; |
| |
| DE_ASSERT(dst.getDataSize() == dataSize); |
| |
| if (tcu::isAstcFormat(format)) |
| { |
| // generate data that is valid in LDR mode |
| const int BLOCK_SIZE = 16; |
| const uint8_t block[BLOCK_SIZE] = {252, 253, 255, 255, 255, 255, 255, 255, |
| 223, 251, 28, 206, 54, 251, 160, 174}; |
| |
| DE_ASSERT(blockByteSize == BLOCK_SIZE); |
| for (int ndx = 0; ndx < numTotalBlocks; ++ndx) |
| deMemcpy((uint8_t *)dst.getData() + ndx * BLOCK_SIZE, block, BLOCK_SIZE); |
| } |
| else |
| { |
| // any data is ok |
| de::Random rnd(0xabc); |
| |
| for (int ndx = 0; ndx < dataSize; ++ndx) |
| ((uint8_t *)dst.getData())[ndx] = rnd.getUint8(); |
| } |
| } |
| |
| template <typename T> |
| struct TextureTraits |
| { |
| }; |
| |
| template <> |
| struct TextureTraits<glu::Texture2D> |
| { |
| typedef tcu::IVec2 SizeType; |
| |
| static de::MovePtr<glu::Texture2D> createTextureFromInternalFormat(glu::RenderContext &renderCtx, |
| uint32_t texFormat, const tcu::IVec2 &size) |
| { |
| return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, size.x(), size.y())); |
| } |
| |
| static de::MovePtr<glu::Texture2D> createTextureFromFormatAndType(glu::RenderContext &renderCtx, uint32_t texFormat, |
| uint32_t type, const tcu::IVec2 &size) |
| { |
| return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, type, size.x(), size.y())); |
| } |
| |
| static de::MovePtr<glu::Texture2D> createTextureFromCompressedData( |
| glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, const tcu::CompressedTexture &compressedLevel, |
| const tcu::TexDecompressionParams &decompressionParams) |
| { |
| return de::MovePtr<glu::Texture2D>( |
| new glu::Texture2D(renderCtx, ctxInfo, 1, &compressedLevel, decompressionParams)); |
| } |
| |
| static int getTextureNumLayers(const tcu::IVec2 &size) |
| { |
| // 2D textures have one layer |
| DE_UNREF(size); |
| return 1; |
| } |
| }; |
| |
| template <> |
| struct TextureTraits<glu::Texture3D> |
| { |
| typedef tcu::IVec3 SizeType; |
| |
| static de::MovePtr<glu::Texture3D> createTextureFromInternalFormat(glu::RenderContext &renderCtx, |
| uint32_t texFormat, const tcu::IVec3 &size) |
| { |
| return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, size.x(), size.y(), size.z())); |
| } |
| |
| static de::MovePtr<glu::Texture3D> createTextureFromFormatAndType(glu::RenderContext &renderCtx, uint32_t texFormat, |
| uint32_t type, const tcu::IVec3 &size) |
| { |
| return de::MovePtr<glu::Texture3D>( |
| new glu::Texture3D(renderCtx, texFormat, type, size.x(), size.y(), size.z())); |
| } |
| |
| static de::MovePtr<glu::Texture3D> createTextureFromCompressedData( |
| glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, const tcu::CompressedTexture &compressedLevel, |
| const tcu::TexDecompressionParams &decompressionParams) |
| { |
| return de::MovePtr<glu::Texture3D>( |
| new glu::Texture3D(renderCtx, ctxInfo, 1, &compressedLevel, decompressionParams)); |
| } |
| |
| static int getTextureNumLayers(const tcu::IVec3 &size) |
| { |
| // 3D textures have Z layers |
| return size.z(); |
| } |
| }; |
| |
| template <typename T> |
| de::MovePtr<T> genDummyTexture(glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, uint32_t texFormat, |
| const typename TextureTraits<T>::SizeType &size) |
| { |
| de::MovePtr<T> texture; |
| |
| if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH) || isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL)) |
| { |
| // fill different channels with different gradients |
| texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size); |
| texture->getRefTexture().allocLevel(0); |
| |
| if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH)) |
| { |
| // fill depth with 0 -> 1 |
| const tcu::PixelBufferAccess depthAccess = |
| tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_DEPTH); |
| tcu::fillWithComponentGradients(depthAccess, tcu::Vec4(0.0f), tcu::Vec4(1.0f)); |
| } |
| |
| if (isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL)) |
| { |
| // fill stencil with 0 -> max |
| const tcu::PixelBufferAccess stencilAccess = |
| tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_STENCIL); |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(stencilAccess.getFormat()); |
| |
| // Flip y to make stencil and depth cases not look identical |
| tcu::fillWithComponentGradients(tcu::flipYAccess(stencilAccess), texFormatInfo.valueMax, |
| texFormatInfo.valueMin); |
| } |
| |
| texture->upload(); |
| } |
| else if (!glu::isCompressedFormat(texFormat)) |
| { |
| if (texFormat == GL_LUMINANCE || texFormat == GL_LUMINANCE_ALPHA || texFormat == GL_ALPHA || |
| texFormat == GL_BGRA) |
| texture = TextureTraits<T>::createTextureFromFormatAndType(renderCtx, texFormat, GL_UNSIGNED_BYTE, size); |
| else |
| texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size); |
| |
| // Fill level 0. |
| texture->getRefTexture().allocLevel(0); |
| |
| // fill with gradient min -> max |
| { |
| const tcu::TextureFormatInfo texFormatInfo = |
| tcu::getTextureFormatInfo(texture->getRefTexture().getFormat()); |
| const tcu::Vec4 rampLow = texFormatInfo.valueMin; |
| const tcu::Vec4 rampHigh = texFormatInfo.valueMax; |
| tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(0), rampLow, rampHigh); |
| } |
| |
| texture->upload(); |
| } |
| else |
| { |
| const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat); |
| const int numLayers = TextureTraits<T>::getTextureNumLayers(size); |
| tcu::CompressedTexture compressedLevel(compressedFormat, size.x(), size.y(), numLayers); |
| const bool isAstcFormat = tcu::isAstcFormat(compressedFormat); |
| tcu::TexDecompressionParams decompressionParams((isAstcFormat) ? (tcu::TexDecompressionParams::ASTCMODE_LDR) : |
| (tcu::TexDecompressionParams::ASTCMODE_LAST)); |
| |
| generateDummyCompressedData(compressedLevel, compressedFormat); |
| |
| texture = |
| TextureTraits<T>::createTextureFromCompressedData(renderCtx, ctxInfo, compressedLevel, decompressionParams); |
| } |
| |
| return texture; |
| } |
| |
| int getNBitIntegerMaxValue(bool isSigned, int numBits) |
| { |
| DE_ASSERT(numBits < 32); |
| |
| if (numBits == 0) |
| return 0; |
| else if (isSigned) |
| return deIntMaxValue32(numBits); |
| else |
| return deUintMaxValue32(numBits); |
| } |
| |
| int getNBitIntegerMinValue(bool isSigned, int numBits) |
| { |
| DE_ASSERT(numBits < 32); |
| |
| if (numBits == 0) |
| return 0; |
| else if (isSigned) |
| return deIntMinValue32(numBits); |
| else |
| return 0; |
| } |
| |
| tcu::IVec4 getNBitIntegerVec4MaxValue(bool isSigned, const tcu::IVec4 &numBits) |
| { |
| return tcu::IVec4(getNBitIntegerMaxValue(isSigned, numBits[0]), getNBitIntegerMaxValue(isSigned, numBits[1]), |
| getNBitIntegerMaxValue(isSigned, numBits[2]), getNBitIntegerMaxValue(isSigned, numBits[3])); |
| } |
| |
| tcu::IVec4 getNBitIntegerVec4MinValue(bool isSigned, const tcu::IVec4 &numBits) |
| { |
| return tcu::IVec4(getNBitIntegerMinValue(isSigned, numBits[0]), getNBitIntegerMinValue(isSigned, numBits[1]), |
| getNBitIntegerMinValue(isSigned, numBits[2]), getNBitIntegerMinValue(isSigned, numBits[3])); |
| } |
| |
| rr::GenericVec4 mapToFormatColorUnits(const tcu::TextureFormat &texFormat, const tcu::Vec4 &normalizedRange) |
| { |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); |
| |
| switch (tcu::getTextureChannelClass(texFormat.type)) |
| { |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| return rr::GenericVec4(normalizedRange); |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| return rr::GenericVec4(normalizedRange * 2.0f - 1.0f); |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| return rr::GenericVec4(texFormatInfo.valueMin + normalizedRange * texFormatInfo.valueMax); |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| return rr::GenericVec4( |
| tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<int32_t>()); |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| return rr::GenericVec4( |
| tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<uint32_t>()); |
| |
| default: |
| DE_ASSERT(false); |
| return rr::GenericVec4(); |
| } |
| } |
| |
| rr::GenericVec4 mapToFormatColorRepresentable(const tcu::TextureFormat &texFormat, const tcu::Vec4 &normalizedRange) |
| { |
| // make sure value is representable in the target format and clear channels |
| // not present in the target format. |
| |
| const rr::GenericVec4 inFormatUnits = mapToFormatColorUnits(texFormat, normalizedRange); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(texFormat); |
| de::ArrayBuffer<uint8_t, 4> buffer(texFormat.getPixelSize()); |
| tcu::PixelBufferAccess access(texFormat, tcu::IVec3(1, 1, 1), buffer.getPtr()); |
| |
| if (tcu::isSRGB(texFormat)) |
| { |
| DE_ASSERT(texFormat.type == tcu::TextureFormat::UNORM_INT8); |
| |
| // make sure border color (in linear space) can be converted to 8-bit sRGB space without |
| // significant loss. |
| const tcu::Vec4 sRGB = tcu::linearToSRGB(normalizedRange); |
| const tcu::IVec4 sRGB8 = tcu::IVec4(tcu::floatToU8(sRGB[0]), tcu::floatToU8(sRGB[1]), tcu::floatToU8(sRGB[2]), |
| tcu::floatToU8(sRGB[3])); |
| const tcu::Vec4 linearized = tcu::sRGBToLinear(tcu::Vec4((float)sRGB8[0] / 255.0f, (float)sRGB8[1] / 255.0f, |
| (float)sRGB8[2] / 255.0f, (float)sRGB8[3] / 255.0f)); |
| |
| return rr::GenericVec4(tcu::select(linearized, tcu::Vec4(0.0f), channelMask)); |
| } |
| |
| switch (tcu::getTextureChannelClass(texFormat.type)) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| { |
| access.setPixel(inFormatUnits.get<float>(), 0, 0); |
| return rr::GenericVec4(tcu::select(access.getPixel(0, 0), tcu::Vec4(0.0f), channelMask)); |
| } |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| { |
| access.setPixel(inFormatUnits.get<int32_t>(), 0, 0); |
| return rr::GenericVec4(tcu::select(access.getPixelInt(0, 0), tcu::IVec4(0), channelMask)); |
| } |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| { |
| access.setPixel(inFormatUnits.get<uint32_t>(), 0, 0); |
| return rr::GenericVec4(tcu::select(access.getPixelUint(0, 0), tcu::UVec4(0u), channelMask)); |
| } |
| default: |
| { |
| DE_ASSERT(false); |
| return rr::GenericVec4(); |
| } |
| } |
| } |
| |
| bool isCoreFilterableFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode) |
| { |
| const bool isLuminanceOrAlpha = (format == GL_LUMINANCE || format == GL_ALPHA || |
| format == GL_LUMINANCE_ALPHA); // special case for luminance/alpha |
| const bool isUnsizedColorFormat = (format == GL_BGRA); |
| const bool isCompressed = glu::isCompressedFormat(format); |
| const bool isDepth = isDepthFormat(format, mode); |
| const bool isStencil = isStencilFormat(format, mode); |
| |
| // special cases |
| if (isLuminanceOrAlpha || isUnsizedColorFormat || isCompressed) |
| return true; |
| if (isStencil || isDepth) |
| return false; |
| |
| // color case |
| return glu::isGLInternalColorFormatFilterable(format); |
| } |
| |
| class TextureBorderClampTest : public TestCase |
| { |
| public: |
| enum StateType |
| { |
| STATE_SAMPLER_PARAM = 0, |
| STATE_TEXTURE_PARAM, |
| |
| STATE_LAST |
| }; |
| |
| enum SamplingFunction |
| { |
| SAMPLE_FILTER = 0, |
| SAMPLE_GATHER, |
| |
| SAMPLE_LAST |
| }; |
| |
| enum Flag |
| { |
| FLAG_USE_SHADOW_SAMPLER = (1u << 0), |
| }; |
| |
| struct IterationConfig |
| { |
| tcu::Vec2 p0; |
| tcu::Vec2 p1; |
| rr::GenericVec4 borderColor; |
| tcu::Vec4 lookupScale; |
| tcu::Vec4 lookupBias; |
| uint32_t minFilter; |
| uint32_t magFilter; |
| std::string description; |
| uint32_t sWrapMode; |
| uint32_t tWrapMode; |
| uint32_t compareMode; |
| float compareRef; |
| }; |
| |
| TextureBorderClampTest(Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, StateType stateType, int texWidth, int texHeight, |
| SamplingFunction samplingFunction, uint32_t flags = 0); |
| ~TextureBorderClampTest(void); |
| |
| protected: |
| void init(void); |
| void deinit(void); |
| |
| private: |
| IterateResult iterate(void); |
| |
| void logParams(const IterationConfig &config, const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| void renderTo(tcu::Surface &surface, const IterationConfig &config, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| void renderQuad(const float *texCoord, const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| void verifyImage(const tcu::Surface &image, const IterationConfig &config, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| bool verifyTextureSampleResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::LodPrecision &lodPrecision, const tcu::LookupPrecision &lookupPrecision); |
| |
| bool verifyTextureCompareResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::TexComparePrecision &texComparePrecision, |
| const tcu::TexComparePrecision &lowQualityTexComparePrecision, |
| const tcu::LodPrecision &lodPrecision, |
| const tcu::LodPrecision &lowQualityLodPrecision); |
| |
| bool verifyTextureGatherResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::LookupPrecision &lookupPrecision); |
| |
| bool verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::TexComparePrecision &texComparePrecision, |
| const tcu::TexComparePrecision &lowQualityTexComparePrecision); |
| |
| uint32_t getIterationSeed(const IterationConfig &config) const; |
| glu::TextureTestUtil::ReferenceParams genSamplerParams(const IterationConfig &config) const; |
| glu::ShaderProgram *genGatherProgram(void) const; |
| |
| virtual int getNumIterations(void) const = 0; |
| virtual IterationConfig getIteration(int ndx) const = 0; |
| |
| protected: |
| const glu::Texture2D *getTexture(void) const; |
| |
| const uint32_t m_texFormat; |
| const tcu::Sampler::DepthStencilMode m_sampleMode; |
| const tcu::TextureChannelClass m_channelClass; |
| const StateType m_stateType; |
| |
| const int m_texHeight; |
| const int m_texWidth; |
| |
| const SamplingFunction m_samplingFunction; |
| const bool m_useShadowSampler; |
| |
| private: |
| enum |
| { |
| VIEWPORT_WIDTH = 128, |
| VIEWPORT_HEIGHT = 128, |
| }; |
| |
| de::MovePtr<glu::Texture2D> m_texture; |
| de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer; |
| de::MovePtr<glu::ShaderProgram> m_gatherProgram; |
| |
| int m_iterationNdx; |
| tcu::ResultCollector m_result; |
| }; |
| |
| TextureBorderClampTest::TextureBorderClampTest(Context &context, const char *name, const char *description, |
| uint32_t texFormat, tcu::Sampler::DepthStencilMode mode, |
| StateType stateType, int texWidth, int texHeight, |
| SamplingFunction samplingFunction, uint32_t flags) |
| : TestCase(context, name, description) |
| , m_texFormat(texFormat) |
| , m_sampleMode(mode) |
| , m_channelClass(getFormatChannelClass(texFormat, mode)) |
| , m_stateType(stateType) |
| , m_texHeight(texHeight) |
| , m_texWidth(texWidth) |
| , m_samplingFunction(samplingFunction) |
| , m_useShadowSampler((flags & FLAG_USE_SHADOW_SAMPLER) != 0) |
| , m_iterationNdx(0) |
| , m_result(context.getTestContext().getLog()) |
| { |
| DE_ASSERT(stateType < STATE_LAST); |
| DE_ASSERT(samplingFunction < SAMPLE_LAST); |
| // mode must be set for combined depth-stencil formats |
| DE_ASSERT(m_channelClass != tcu::TEXTURECHANNELCLASS_LAST || mode != tcu::Sampler::MODE_LAST); |
| } |
| |
| TextureBorderClampTest::~TextureBorderClampTest(void) |
| { |
| deinit(); |
| } |
| |
| void TextureBorderClampTest::init(void) |
| { |
| // requirements |
| const bool supportsGL45 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)); |
| const bool supportsES32orGL45 = |
| glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || supportsGL45; |
| |
| if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp")) |
| throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension"); |
| |
| if (glu::isCompressedFormat(m_texFormat) && !supportsES32orGL45 && |
| tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) && |
| !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr")) |
| { |
| throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension"); |
| } |
| |
| if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888")) |
| throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension"); |
| |
| if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH || |
| m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT) |
| { |
| throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + |
| de::toString<int>(VIEWPORT_HEIGHT) + " viewport"); |
| } |
| |
| // resources |
| |
| m_texture = genDummyTexture<glu::Texture2D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, |
| tcu::IVec2(m_texWidth, m_texHeight)); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "Created texture with format " |
| << glu::getTextureFormatName(m_texFormat) << ", size (" << m_texture->getRefTexture().getWidth() |
| << ", " << m_texture->getRefTexture().getHeight() << ")\n" |
| << "Setting sampling state using " |
| << ((m_stateType == STATE_TEXTURE_PARAM) ? ("texture state") : ("sampler state")) |
| << tcu::TestLog::EndMessage; |
| |
| if (m_samplingFunction == SAMPLE_FILTER) |
| { |
| const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()); |
| |
| m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer( |
| m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP)); |
| } |
| else |
| { |
| m_gatherProgram = de::MovePtr<glu::ShaderProgram>(genGatherProgram()); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "Using texture gather to sample texture" |
| << tcu::TestLog::EndMessage << *m_gatherProgram; |
| |
| if (!m_gatherProgram->isOk()) |
| throw tcu::TestError("failed to build program"); |
| } |
| } |
| |
| void TextureBorderClampTest::deinit(void) |
| { |
| m_texture.clear(); |
| m_renderer.clear(); |
| m_gatherProgram.clear(); |
| } |
| |
| TextureBorderClampTest::IterateResult TextureBorderClampTest::iterate(void) |
| { |
| const IterationConfig iterationConfig = getIteration(m_iterationNdx); |
| const std::string iterationDesc = |
| "Iteration " + de::toString(m_iterationNdx + 1) + |
| (iterationConfig.description.empty() ? ("") : (" - " + iterationConfig.description)); |
| const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", iterationDesc); |
| tcu::Surface renderedFrame(VIEWPORT_WIDTH, VIEWPORT_HEIGHT); |
| const glu::TextureTestUtil::ReferenceParams samplerParams = genSamplerParams(iterationConfig); |
| |
| logParams(iterationConfig, samplerParams); |
| renderTo(renderedFrame, iterationConfig, samplerParams); |
| verifyImage(renderedFrame, iterationConfig, samplerParams); |
| |
| if (++m_iterationNdx == getNumIterations()) |
| { |
| m_result.setTestContextResult(m_testCtx); |
| return STOP; |
| } |
| return CONTINUE; |
| } |
| |
| void TextureBorderClampTest::logParams(const IterationConfig &config, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const std::string borderColorString = (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? |
| (de::toString(config.borderColor.get<int32_t>())) : |
| (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? |
| (de::toString(config.borderColor.get<uint32_t>())) : |
| (de::toString(config.borderColor.get<float>())); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "Rendering full screen quad, tex coords bottom-left: " << config.p0 |
| << ", top-right " << config.p1 << "\n" |
| << "Border color is " << borderColorString << "\n" |
| << "Texture lookup bias: " << samplerParams.colorBias << "\n" |
| << "Texture lookup scale: " << samplerParams.colorScale << "\n" |
| << "Filters: min = " |
| << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.minFilter)) |
| << ", mag = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.magFilter)) |
| << "\n" |
| << "Wrap mode: s = " << glu::getRepeatModeStr(config.sWrapMode) |
| << ", t = " << glu::getRepeatModeStr(config.tWrapMode) << "\n" |
| << tcu::TestLog::EndMessage; |
| |
| if (m_sampleMode == tcu::Sampler::MODE_DEPTH) |
| m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is DEPTH_COMPONENT" |
| << tcu::TestLog::EndMessage; |
| else if (m_sampleMode == tcu::Sampler::MODE_STENCIL) |
| m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is STENCIL_INDEX" |
| << tcu::TestLog::EndMessage; |
| |
| if (config.compareMode != GL_NONE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Texture mode is COMPARE_REF_TO_TEXTURE, mode = " |
| << glu::getCompareFuncStr(config.compareMode) << "\n" |
| << "Compare reference value = " << config.compareRef << "\n" |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| |
| void TextureBorderClampTest::renderTo(tcu::Surface &surface, const IterationConfig &config, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const glw::Functions &gl = m_context.getRenderContext().getFunctions(); |
| const gls::TextureTestUtil::RandomViewport viewport(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, |
| getIterationSeed(config)); |
| std::vector<float> texCoord; |
| de::MovePtr<glu::Sampler> sampler; |
| |
| glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1); |
| |
| // Bind to unit 0. |
| gl.activeTexture(GL_TEXTURE0); |
| gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture()); |
| |
| if (m_sampleMode == tcu::Sampler::MODE_DEPTH) |
| gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT); |
| else if (m_sampleMode == tcu::Sampler::MODE_STENCIL) |
| gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); |
| |
| if (config.compareMode == GL_NONE) |
| { |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS); |
| } |
| else |
| { |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, config.compareMode); |
| } |
| |
| if (m_stateType == STATE_TEXTURE_PARAM) |
| { |
| // Setup filtering and wrap modes. |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); |
| |
| switch (m_channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| gl.texParameterIiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<int32_t>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| gl.texParameterIuiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<uint32_t>()); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| else if (m_stateType == STATE_SAMPLER_PARAM) |
| { |
| const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f); |
| |
| // Setup filtering and wrap modes to bad values |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blue.getPtr()); // just set some unlikely color |
| |
| // setup sampler to correct values |
| sampler = de::MovePtr<glu::Sampler>(new glu::Sampler(m_context.getRenderContext())); |
| |
| gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); |
| gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); |
| gl.samplerParameteri(**sampler, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); |
| gl.samplerParameteri(**sampler, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); |
| |
| switch (m_channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| gl.samplerParameterfv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| gl.samplerParameterIiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<int32_t>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| gl.samplerParameterIuiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<uint32_t>()); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| |
| gl.bindSampler(0, **sampler); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); |
| |
| gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); |
| renderQuad(&texCoord[0], samplerParams); |
| glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess()); |
| } |
| |
| void TextureBorderClampTest::renderQuad(const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| // use TextureRenderer for basic rendering, use custom for gather |
| if (m_samplingFunction == SAMPLE_FILTER) |
| m_renderer->renderQuad(0, texCoord, samplerParams); |
| else |
| { |
| static const float position[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f, |
| +1.0f, -1.0f, 0.0f, 1.0f, +1.0f, +1.0f, 0.0f, 1.0f}; |
| static const uint16_t indices[] = {0, 1, 2, 2, 1, 3}; |
| const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 4, 4, 0, &position[0]), |
| glu::va::Float("a_texcoord", 2, 4, 0, texCoord)}; |
| |
| const glw::Functions &gl = m_context.getRenderContext().getFunctions(); |
| const uint32_t progId = m_gatherProgram->getProgram(); |
| |
| gl.useProgram(progId); |
| gl.uniform1i(gl.getUniformLocation(progId, "u_sampler"), 0); |
| if (m_useShadowSampler) |
| gl.uniform1f(gl.getUniformLocation(progId, "u_ref"), samplerParams.ref); |
| gl.uniform4fv(gl.getUniformLocation(progId, "u_colorScale"), 1, samplerParams.colorScale.getPtr()); |
| gl.uniform4fv(gl.getUniformLocation(progId, "u_colorBias"), 1, samplerParams.colorBias.getPtr()); |
| |
| glu::draw(m_context.getRenderContext(), progId, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], |
| glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); |
| } |
| } |
| |
| void TextureBorderClampTest::verifyImage(const tcu::Surface &renderedFrame, const IterationConfig &config, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| |
| tcu::LodPrecision lodPrecision; |
| std::vector<float> texCoord; |
| bool verificationOk; |
| |
| glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1); |
| |
| lodPrecision.derivateBits = 18; |
| lodPrecision.lodBits = 5; |
| |
| if (samplerParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE) |
| { |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode); |
| const bool isNearestMinFilter = samplerParams.sampler.minFilter == tcu::Sampler::NEAREST || |
| samplerParams.sampler.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST; |
| const bool isNearestMagFilter = samplerParams.sampler.magFilter == tcu::Sampler::NEAREST; |
| const bool isNearestOnly = isNearestMinFilter && isNearestMagFilter; |
| const bool isSRGB = texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA; |
| const int colorErrorBits = (isNearestOnly && !isSRGB) ? (1) : (2); |
| const tcu::IVec4 colorBits = |
| tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); |
| tcu::LookupPrecision lookupPrecision; |
| |
| lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale; |
| lookupPrecision.coordBits = tcu::IVec3(20, 20, 0); |
| lookupPrecision.uvwBits = tcu::IVec3(5, 5, 0); |
| lookupPrecision.colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); |
| |
| if (m_samplingFunction == SAMPLE_FILTER) |
| { |
| verificationOk = verifyTextureSampleResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, |
| lodPrecision, lookupPrecision); |
| } |
| else if (m_samplingFunction == SAMPLE_GATHER) |
| { |
| verificationOk = |
| verifyTextureGatherResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, lookupPrecision); |
| } |
| else |
| { |
| DE_ASSERT(false); |
| verificationOk = false; |
| } |
| } |
| else |
| { |
| tcu::TexComparePrecision texComparePrecision; |
| tcu::TexComparePrecision lowQualityTexComparePrecision; |
| tcu::LodPrecision lowQualityLodPrecision = lodPrecision; |
| |
| texComparePrecision.coordBits = tcu::IVec3(20, 20, 0); |
| texComparePrecision.uvwBits = tcu::IVec3(7, 7, 0); |
| texComparePrecision.pcfBits = 5; |
| texComparePrecision.referenceBits = 16; |
| texComparePrecision.resultBits = de::max(0, pixelFormat.redBits - 1); |
| |
| lowQualityTexComparePrecision.coordBits = tcu::IVec3(20, 20, 0); |
| lowQualityTexComparePrecision.uvwBits = tcu::IVec3(4, 4, 0); |
| lowQualityTexComparePrecision.pcfBits = 0; |
| lowQualityTexComparePrecision.referenceBits = 16; |
| lowQualityTexComparePrecision.resultBits = de::max(0, pixelFormat.redBits - 1); |
| |
| lowQualityLodPrecision.lodBits = 4; |
| |
| if (m_samplingFunction == SAMPLE_FILTER) |
| { |
| verificationOk = |
| verifyTextureCompareResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, texComparePrecision, |
| lowQualityTexComparePrecision, lodPrecision, lowQualityLodPrecision); |
| } |
| else if (m_samplingFunction == SAMPLE_GATHER) |
| { |
| verificationOk = verifyTextureGatherCmpResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, |
| texComparePrecision, lowQualityTexComparePrecision); |
| } |
| else |
| { |
| DE_ASSERT(false); |
| verificationOk = false; |
| } |
| } |
| |
| if (!verificationOk) |
| m_result.fail("Image verification failed"); |
| } |
| |
| bool TextureBorderClampTest::verifyTextureSampleResult(const tcu::ConstPixelBufferAccess &renderedFrame, |
| const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::LodPrecision &lodPrecision, |
| const tcu::LookupPrecision &lookupPrecision) |
| { |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| int numFailedPixels; |
| |
| glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), |
| texCoord, samplerParams); |
| |
| numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff( |
| renderedFrame, reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(), texCoord, |
| samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog()); |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels |
| << " invalid pixels!" << tcu::TestLog::EndMessage; |
| m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") |
| << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); |
| } |
| m_testCtx.getLog() << tcu::TestLog::EndImageSet; |
| |
| return (numFailedPixels == 0); |
| } |
| |
| bool TextureBorderClampTest::verifyTextureCompareResult(const tcu::ConstPixelBufferAccess &renderedFrame, |
| const float *texCoord, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::TexComparePrecision &texComparePrecision, |
| const tcu::TexComparePrecision &lowQualityTexComparePrecision, |
| const tcu::LodPrecision &lodPrecision, |
| const tcu::LodPrecision &lowQualityLodPrecision) |
| { |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| const int colorErrorBits = 1; |
| const tcu::IVec4 nonShadowBits = |
| tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); |
| const tcu::Vec3 nonShadowThreshold = tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1, 2, 3); |
| std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; |
| const tcu::Texture2DView effectiveView = |
| tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); |
| tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| int numFailedPixels; |
| |
| glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), effectiveView, texCoord, |
| samplerParams); |
| |
| numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff( |
| renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, texCoord, samplerParams, |
| texComparePrecision, lodPrecision, nonShadowThreshold); |
| |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Warning: Verification assuming high-quality PCF filtering failed." |
| << tcu::TestLog::EndMessage; |
| |
| numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff( |
| renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, texCoord, samplerParams, |
| lowQualityTexComparePrecision, lowQualityLodPrecision, nonShadowThreshold); |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "ERROR: Verification against low precision requirements failed, failing test case." |
| << tcu::TestLog::EndMessage; |
| else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) |
| m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); |
| } |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels |
| << " invalid pixels!" << tcu::TestLog::EndMessage; |
| m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") |
| << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); |
| } |
| m_testCtx.getLog() << tcu::TestLog::EndImageSet; |
| |
| return (numFailedPixels == 0); |
| } |
| |
| template <typename T> |
| static inline T triQuadInterpolate(const T (&values)[4], float xFactor, float yFactor) |
| { |
| if (xFactor + yFactor < 1.0f) |
| return values[0] + (values[2] - values[0]) * xFactor + (values[1] - values[0]) * yFactor; |
| else |
| return values[3] + (values[1] - values[3]) * (1.0f - xFactor) + (values[2] - values[3]) * (1.0f - yFactor); |
| } |
| |
| bool TextureBorderClampTest::verifyTextureGatherResult(const tcu::ConstPixelBufferAccess &renderedFrame, |
| const float *texCoordArray, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::LookupPrecision &lookupPrecision) |
| { |
| const tcu::Vec2 texCoords[4] = { |
| tcu::Vec2(texCoordArray[0], texCoordArray[1]), |
| tcu::Vec2(texCoordArray[2], texCoordArray[3]), |
| tcu::Vec2(texCoordArray[4], texCoordArray[5]), |
| tcu::Vec2(texCoordArray[6], texCoordArray[7]), |
| }; |
| |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| const uint8_t fbColormask = tcu::getColorMask(pixelFormat); |
| |
| std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; |
| const tcu::Texture2DView effectiveView = |
| tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); |
| |
| tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| int numFailedPixels = 0; |
| |
| tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); |
| |
| for (int py = 0; py < reference.getHeight(); ++py) |
| for (int px = 0; px < reference.getWidth(); ++px) |
| { |
| const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / |
| tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight()); |
| const tcu::Vec2 texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y()); |
| const tcu::Vec4 referenceValue = effectiveView.gatherOffsets( |
| samplerParams.sampler, texCoord.x(), texCoord.y(), 0, glu::getDefaultGatherOffsets()); |
| const tcu::Vec4 referencePixel = referenceValue * samplerParams.colorScale + samplerParams.colorBias; |
| const tcu::Vec4 resultPixel = renderedFrame.getPixel(px, py); |
| const tcu::Vec4 resultValue = (resultPixel - samplerParams.colorBias) / samplerParams.colorScale; |
| |
| reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask)); |
| |
| if (tcu::boolAny(tcu::logicalAnd( |
| lookupPrecision.colorMask, |
| tcu::greaterThan(tcu::absDiff(resultPixel, referencePixel), lookupPrecision.colorThreshold)))) |
| { |
| if (!tcu::isGatherOffsetsResultValid(effectiveView, samplerParams.sampler, lookupPrecision, texCoord, 0, |
| glu::getDefaultGatherOffsets(), resultValue)) |
| { |
| errorMask.setPixel(px, py, tcu::RGBA::red()); |
| ++numFailedPixels; |
| } |
| } |
| } |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels |
| << " invalid pixels!" << tcu::TestLog::EndMessage; |
| m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") |
| << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); |
| } |
| m_testCtx.getLog() << tcu::TestLog::EndImageSet; |
| |
| return (numFailedPixels == 0); |
| } |
| |
| bool TextureBorderClampTest::verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess &renderedFrame, |
| const float *texCoordArray, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams, |
| const tcu::TexComparePrecision &texComparePrecision, |
| const tcu::TexComparePrecision &lowQualityTexComparePrecision) |
| { |
| const tcu::Vec2 texCoords[4] = { |
| tcu::Vec2(texCoordArray[0], texCoordArray[1]), |
| tcu::Vec2(texCoordArray[2], texCoordArray[3]), |
| tcu::Vec2(texCoordArray[4], texCoordArray[5]), |
| tcu::Vec2(texCoordArray[6], texCoordArray[7]), |
| }; |
| |
| std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; |
| const tcu::Texture2DView effectiveView = |
| tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); |
| |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| const tcu::BVec4 colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); |
| const uint8_t fbColormask = tcu::getColorMask(pixelFormat); |
| tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| int numFailedPixels = 0; |
| bool lowQuality = false; |
| |
| tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); |
| |
| for (int py = 0; py < reference.getHeight(); ++py) |
| for (int px = 0; px < reference.getWidth(); ++px) |
| { |
| const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / |
| tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight()); |
| const tcu::Vec2 texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y()); |
| const float refZ = samplerParams.ref; |
| const tcu::Vec4 referenceValue = effectiveView.gatherOffsetsCompare( |
| samplerParams.sampler, refZ, texCoord.x(), texCoord.y(), glu::getDefaultGatherOffsets()); |
| const tcu::Vec4 resultValue = renderedFrame.getPixel(px, py); |
| |
| reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask)); |
| |
| if (tcu::boolAny(tcu::logicalAnd(colorMask, tcu::notEqual(referenceValue, resultValue)))) |
| { |
| if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, texComparePrecision, |
| texCoord, glu::getDefaultGatherOffsets(), refZ, |
| resultValue)) |
| { |
| lowQuality = true; |
| |
| // fall back to low quality verification |
| if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, |
| lowQualityTexComparePrecision, texCoord, |
| glu::getDefaultGatherOffsets(), refZ, resultValue)) |
| { |
| errorMask.setPixel(px, py, tcu::RGBA::red()); |
| ++numFailedPixels; |
| } |
| } |
| } |
| } |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels |
| << " invalid pixels!" << tcu::TestLog::EndMessage; |
| else if (lowQuality) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Warning: Verification assuming high-quality PCF filtering failed." |
| << tcu::TestLog::EndMessage; |
| m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); |
| } |
| |
| m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") |
| << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); |
| } |
| m_testCtx.getLog() << tcu::TestLog::EndImageSet; |
| |
| return (numFailedPixels == 0); |
| } |
| |
| const glu::Texture2D *TextureBorderClampTest::getTexture(void) const |
| { |
| return m_texture.get(); |
| } |
| |
| uint32_t TextureBorderClampTest::getIterationSeed(const IterationConfig &config) const |
| { |
| tcu::SeedBuilder builder; |
| builder << std::string(getName()) << m_iterationNdx << m_texFormat << config.minFilter << config.magFilter |
| << m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight(); |
| return builder.get(); |
| } |
| |
| glu::TextureTestUtil::ReferenceParams TextureBorderClampTest::genSamplerParams(const IterationConfig &config) const |
| { |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode); |
| glu::TextureTestUtil::ReferenceParams refParams(glu::TextureTestUtil::TEXTURETYPE_2D); |
| |
| refParams.sampler = glu::mapGLSampler(config.sWrapMode, config.tWrapMode, config.minFilter, config.magFilter); |
| refParams.sampler.borderColor = config.borderColor; |
| refParams.sampler.compare = |
| (!m_useShadowSampler) ? (tcu::Sampler::COMPAREMODE_NONE) : (glu::mapGLCompareFunc(config.compareMode)); |
| refParams.sampler.depthStencilMode = m_sampleMode; |
| refParams.lodMode = glu::TextureTestUtil::LODMODE_EXACT; |
| refParams.samplerType = (!m_useShadowSampler) ? (glu::TextureTestUtil::getSamplerType(texFormat)) : |
| (glu::TextureTestUtil::SAMPLERTYPE_SHADOW); |
| refParams.colorScale = config.lookupScale; |
| refParams.colorBias = config.lookupBias; |
| refParams.ref = config.compareRef; |
| |
| // compare can only be used with depth textures |
| if (!isDepthFormat(m_texFormat, m_sampleMode)) |
| DE_ASSERT(refParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE); |
| |
| // sampler type must match compare mode |
| DE_ASSERT(m_useShadowSampler == (config.compareMode != GL_NONE)); |
| |
| // in gather, weird mapping is most likely an error |
| if (m_samplingFunction == SAMPLE_GATHER) |
| { |
| DE_ASSERT(refParams.colorScale == tcu::Vec4(refParams.colorScale.x())); |
| DE_ASSERT(refParams.colorBias == tcu::Vec4(refParams.colorBias.x())); |
| } |
| |
| return refParams; |
| } |
| |
| glu::ShaderProgram *TextureBorderClampTest::genGatherProgram(void) const |
| { |
| const std::string glslVersionDecl = |
| glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType())); |
| const std::string vtxSource = glslVersionDecl + "\n" |
| "in highp vec4 a_position;\n" |
| "in highp vec2 a_texcoord;\n" |
| "out highp vec2 v_texcoord;\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = a_position;\n" |
| " v_texcoord = a_texcoord;\n" |
| "}\n"; |
| const char *samplerType; |
| const char *lookup; |
| std::ostringstream fragSource; |
| |
| if (m_useShadowSampler) |
| { |
| samplerType = "sampler2DShadow"; |
| lookup = "textureGather(u_sampler, v_texcoord, u_ref)"; |
| } |
| else |
| { |
| switch (m_channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| samplerType = "sampler2D"; |
| lookup = "textureGather(u_sampler, v_texcoord)"; |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| samplerType = "isampler2D"; |
| lookup = "vec4(textureGather(u_sampler, v_texcoord))"; |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| samplerType = "usampler2D"; |
| lookup = "vec4(textureGather(u_sampler, v_texcoord))"; |
| break; |
| |
| default: |
| samplerType = ""; |
| lookup = ""; |
| DE_ASSERT(false); |
| } |
| } |
| |
| fragSource << glslVersionDecl + "\n" |
| "uniform highp " |
| << samplerType |
| << " u_sampler;\n" |
| "uniform highp vec4 u_colorScale;\n" |
| "uniform highp vec4 u_colorBias;\n" |
| << ((m_useShadowSampler) ? ("uniform highp float u_ref;\n") : ("")) |
| << "in highp vec2 v_texcoord;\n" |
| "layout(location=0) out highp vec4 o_color;\n" |
| "void main()\n" |
| "{\n" |
| " o_color = " |
| << lookup |
| << " * u_colorScale + u_colorBias;\n" |
| "}\n"; |
| |
| return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() |
| << glu::VertexSource(vtxSource) |
| << glu::FragmentSource(fragSource.str())); |
| } |
| |
| class TextureBorderClampFormatCase : public TextureBorderClampTest |
| { |
| public: |
| TextureBorderClampFormatCase(Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, StateType stateType, SizeType sizeType, |
| uint32_t filter, SamplingFunction samplingFunction); |
| |
| private: |
| void init(void); |
| |
| int getNumIterations(void) const; |
| IterationConfig getIteration(int ndx) const; |
| |
| const SizeType m_sizeType; |
| const uint32_t m_filter; |
| |
| std::vector<IterationConfig> m_iterations; |
| }; |
| |
| TextureBorderClampFormatCase::TextureBorderClampFormatCase(Context &context, const char *name, const char *description, |
| uint32_t texFormat, tcu::Sampler::DepthStencilMode mode, |
| StateType stateType, SizeType sizeType, uint32_t filter, |
| SamplingFunction samplingFunction) |
| : TextureBorderClampTest(context, name, description, texFormat, mode, stateType, |
| (sizeType == SIZE_POT) ? (32) : (17), (sizeType == SIZE_POT) ? (16) : (31), |
| samplingFunction) |
| , m_sizeType(sizeType) |
| , m_filter(filter) |
| { |
| if (m_sizeType == SIZE_POT) |
| DE_ASSERT(deIsPowerOfTwo32(m_texWidth) && deIsPowerOfTwo32(m_texHeight)); |
| else |
| DE_ASSERT(!deIsPowerOfTwo32(m_texWidth) && !deIsPowerOfTwo32(m_texHeight)); |
| |
| if (glu::isCompressedFormat(texFormat)) |
| { |
| const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat); |
| const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(compressedFormat); |
| |
| // is (not) multiple of a block size |
| if (m_sizeType == SIZE_POT) |
| DE_ASSERT((m_texWidth % blockPixelSize.x()) == 0 && (m_texHeight % blockPixelSize.y()) == 0); |
| else |
| DE_ASSERT((m_texWidth % blockPixelSize.x()) != 0 && (m_texHeight % blockPixelSize.y()) != 0); |
| |
| DE_UNREF(blockPixelSize); |
| } |
| } |
| |
| void TextureBorderClampFormatCase::init(void) |
| { |
| TextureBorderClampTest::init(); |
| |
| // \note TextureBorderClampTest::init() creates texture |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); |
| |
| // iterations |
| |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-1.5f, -3.0f); |
| iteration.p1 = tcu::Vec2(1.5f, 2.5f); |
| iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.3f, 0.7f, 0.2f, 0.5f)); |
| m_iterations.push_back(iteration); |
| } |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.5f, 0.75f); |
| iteration.p1 = tcu::Vec2(0.25f, 1.25f); |
| iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.9f, 0.2f, 0.4f, 0.6f)); |
| m_iterations.push_back(iteration); |
| } |
| |
| // common parameters |
| for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) |
| { |
| IterationConfig &iteration = m_iterations[ndx]; |
| |
| if (m_samplingFunction == SAMPLE_GATHER) |
| { |
| iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x()); |
| iteration.lookupBias = tcu::Vec4(texFormatInfo.lookupBias.x()); |
| } |
| else |
| { |
| iteration.lookupScale = texFormatInfo.lookupScale; |
| iteration.lookupBias = texFormatInfo.lookupBias; |
| } |
| |
| iteration.minFilter = m_filter; |
| iteration.magFilter = m_filter; |
| iteration.sWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.tWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.compareMode = GL_NONE; |
| iteration.compareRef = 0.0f; |
| } |
| } |
| |
| int TextureBorderClampFormatCase::getNumIterations(void) const |
| { |
| return (int)m_iterations.size(); |
| } |
| |
| TextureBorderClampTest::IterationConfig TextureBorderClampFormatCase::getIteration(int ndx) const |
| { |
| return m_iterations[ndx]; |
| } |
| |
| class TextureBorderClampRangeClampCase : public TextureBorderClampTest |
| { |
| public: |
| TextureBorderClampRangeClampCase(Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, uint32_t filter); |
| |
| private: |
| void init(void); |
| |
| int getNumIterations(void) const; |
| IterationConfig getIteration(int ndx) const; |
| |
| const uint32_t m_filter; |
| std::vector<IterationConfig> m_iterations; |
| }; |
| |
| TextureBorderClampRangeClampCase::TextureBorderClampRangeClampCase(Context &context, const char *name, |
| const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, uint32_t filter) |
| : TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM, |
| 8, 32, SAMPLE_FILTER) |
| , m_filter(filter) |
| { |
| } |
| |
| void TextureBorderClampRangeClampCase::init(void) |
| { |
| TextureBorderClampTest::init(); |
| |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); |
| const bool isDepth = isDepthFormat(m_texFormat, m_sampleMode); |
| const bool isFloat = m_channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT; |
| const bool isFixed = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || |
| m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; |
| const bool isPureInteger = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| |
| if (isDepth || isFloat) |
| { |
| // infinities are commonly used values on depth/float borders |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-1.2f, -3.0f); |
| iteration.p1 = tcu::Vec2(1.2f, 2.5f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity())); |
| iteration.lookupScale = |
| tcu::Vec4(0.5f); // scale & bias to [0.25, 0.5] range to make out-of-range values visible |
| iteration.lookupBias = tcu::Vec4(0.25f); |
| iteration.description = "border value infinity"; |
| m_iterations.push_back(iteration); |
| } |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.25f, -0.75f); |
| iteration.p1 = tcu::Vec2(2.25f, 1.25f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity())); |
| iteration.lookupScale = tcu::Vec4(0.5f); |
| iteration.lookupBias = tcu::Vec4(0.25f); |
| iteration.description = "border value negative infinity"; |
| m_iterations.push_back(iteration); |
| } |
| } |
| else if (isPureInteger) |
| { |
| const tcu::IVec4 numBits = tcu::getTextureFormatBitDepth(texFormat); |
| const bool isSigned = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER; |
| |
| // can't overflow 32bit integers with 32bit integers |
| for (int ndx = 0; ndx < 4; ++ndx) |
| DE_ASSERT(numBits[ndx] == 0 || numBits[ndx] == 8 || numBits[ndx] == 16); |
| |
| const tcu::IVec4 minValue = getNBitIntegerVec4MinValue(isSigned, numBits); |
| const tcu::IVec4 maxValue = getNBitIntegerVec4MaxValue(isSigned, numBits); |
| const tcu::IVec4 valueRange = maxValue - minValue; |
| const tcu::IVec4 divSafeRange( |
| (valueRange[0] == 0) ? (1) : (valueRange[0]), (valueRange[1] == 0) ? (1) : (valueRange[1]), |
| (valueRange[2] == 0) ? (1) : (valueRange[2]), (valueRange[3] == 0) ? (1) : (valueRange[3])); |
| |
| // format max |
| { |
| const tcu::IVec4 value = maxValue + tcu::IVec4(1); |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-1.2f, -3.0f); |
| iteration.p1 = tcu::Vec2(1.2f, 2.5f); |
| iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<uint32_t>())); |
| iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); |
| iteration.lookupBias = (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f)); |
| iteration.description = "border values one larger than maximum"; |
| m_iterations.push_back(iteration); |
| } |
| // format min |
| if (isSigned) |
| { |
| const tcu::IVec4 value = minValue - tcu::IVec4(1); |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.25f, -0.75f); |
| iteration.p1 = tcu::Vec2(2.25f, 1.25f); |
| iteration.borderColor = rr::GenericVec4(value); |
| iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); |
| iteration.lookupBias = tcu::Vec4(0.5f); |
| iteration.description = "border values one less than minimum"; |
| m_iterations.push_back(iteration); |
| } |
| // (u)int32 max |
| { |
| const tcu::IVec4 value = (isSigned) ? (tcu::IVec4(std::numeric_limits<int32_t>::max())) : |
| (tcu::IVec4(std::numeric_limits<uint32_t>::max())); |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-1.6f, -2.1f); |
| iteration.p1 = tcu::Vec2(1.2f, 3.5f); |
| iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<uint32_t>())); |
| iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); |
| iteration.lookupBias = tcu::Vec4(0.25f); |
| iteration.description = "border values 32-bit maximum"; |
| m_iterations.push_back(iteration); |
| } |
| // int32 min |
| if (isSigned) |
| { |
| const tcu::IVec4 value = tcu::IVec4(std::numeric_limits<int32_t>::min()); |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-2.6f, -4.0f); |
| iteration.p1 = tcu::Vec2(1.1f, 1.5f); |
| iteration.borderColor = rr::GenericVec4(value); |
| iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); |
| iteration.lookupBias = tcu::Vec4(0.25f); |
| iteration.description = "border values 0"; |
| m_iterations.push_back(iteration); |
| } |
| } |
| else if (isFixed) |
| { |
| const bool isSigned = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT; |
| ; |
| const tcu::Vec4 lookupBias = |
| (isSigned) ? (tcu::Vec4(0.5f)) : |
| (tcu::Vec4(0.25f)); // scale & bias to [0.25, 0.5] range to make out-of-range values visible |
| const tcu::Vec4 lookupScale = (isSigned) ? (tcu::Vec4(0.25f)) : (tcu::Vec4(0.5f)); |
| |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-1.2f, -3.0f); |
| iteration.p1 = tcu::Vec2(1.2f, 2.5f); |
| iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(1.1f, 1.3f, 2.2f, 1.3f)); |
| iteration.lookupScale = lookupScale; |
| iteration.lookupBias = lookupBias; |
| iteration.description = "border values larger than maximum"; |
| m_iterations.push_back(iteration); |
| } |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.25f, -0.75f); |
| iteration.p1 = tcu::Vec2(2.25f, 1.25f); |
| iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(-0.2f, -0.9f, -2.4f, -0.6f)); |
| iteration.lookupScale = lookupScale; |
| iteration.lookupBias = lookupBias; |
| iteration.description = "border values less than minimum"; |
| m_iterations.push_back(iteration); |
| } |
| } |
| else |
| DE_ASSERT(false); |
| |
| // common parameters |
| for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) |
| { |
| IterationConfig &iteration = m_iterations[ndx]; |
| |
| iteration.minFilter = m_filter; |
| iteration.magFilter = m_filter; |
| iteration.sWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.tWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.compareMode = GL_NONE; |
| iteration.compareRef = 0.0f; |
| } |
| } |
| |
| int TextureBorderClampRangeClampCase::getNumIterations(void) const |
| { |
| return (int)m_iterations.size(); |
| } |
| |
| TextureBorderClampTest::IterationConfig TextureBorderClampRangeClampCase::getIteration(int ndx) const |
| { |
| return m_iterations[ndx]; |
| } |
| |
| class TextureBorderClampPerAxisCase2D : public TextureBorderClampTest |
| { |
| public: |
| TextureBorderClampPerAxisCase2D(Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, SizeType sizeType, uint32_t filter, |
| uint32_t texSWrap, uint32_t texTWrap, SamplingFunction samplingFunction); |
| |
| private: |
| void init(void); |
| |
| int getNumIterations(void) const; |
| IterationConfig getIteration(int ndx) const; |
| |
| const uint32_t m_texSWrap; |
| const uint32_t m_texTWrap; |
| const uint32_t m_filter; |
| |
| std::vector<IterationConfig> m_iterations; |
| }; |
| |
| TextureBorderClampPerAxisCase2D::TextureBorderClampPerAxisCase2D(Context &context, const char *name, |
| const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode mode, SizeType sizeType, |
| uint32_t filter, uint32_t texSWrap, uint32_t texTWrap, |
| SamplingFunction samplingFunction) |
| : TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM, |
| (sizeType == SIZE_POT) ? (16) : (7), (sizeType == SIZE_POT) ? (8) : (9), samplingFunction) |
| , m_texSWrap(texSWrap) |
| , m_texTWrap(texTWrap) |
| , m_filter(filter) |
| { |
| } |
| |
| void TextureBorderClampPerAxisCase2D::init(void) |
| { |
| TextureBorderClampTest::init(); |
| |
| // \note TextureBorderClampTest::init() creates texture |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.25f, -0.75f); |
| iteration.p1 = tcu::Vec2(2.25f, 1.25f); |
| iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.4f, 0.9f, 0.1f, 0.2f)); |
| |
| if (m_samplingFunction == SAMPLE_GATHER) |
| { |
| iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x()); |
| iteration.lookupBias = tcu::Vec4(texFormatInfo.lookupBias.x()); |
| } |
| else |
| { |
| iteration.lookupScale = texFormatInfo.lookupScale; |
| iteration.lookupBias = texFormatInfo.lookupBias; |
| } |
| |
| iteration.minFilter = m_filter; |
| iteration.magFilter = m_filter; |
| iteration.sWrapMode = m_texSWrap; |
| iteration.tWrapMode = m_texTWrap; |
| iteration.compareMode = GL_NONE; |
| iteration.compareRef = 0.0f; |
| |
| m_iterations.push_back(iteration); |
| } |
| |
| int TextureBorderClampPerAxisCase2D::getNumIterations(void) const |
| { |
| return (int)m_iterations.size(); |
| } |
| |
| TextureBorderClampTest::IterationConfig TextureBorderClampPerAxisCase2D::getIteration(int ndx) const |
| { |
| return m_iterations[ndx]; |
| } |
| |
| class TextureBorderClampDepthCompareCase : public TextureBorderClampTest |
| { |
| public: |
| TextureBorderClampDepthCompareCase(Context &context, const char *name, const char *description, uint32_t texFormat, |
| SizeType sizeType, uint32_t filter, SamplingFunction samplingFunction); |
| |
| private: |
| void init(void); |
| |
| int getNumIterations(void) const; |
| IterationConfig getIteration(int ndx) const; |
| |
| const uint32_t m_filter; |
| std::vector<IterationConfig> m_iterations; |
| }; |
| |
| TextureBorderClampDepthCompareCase::TextureBorderClampDepthCompareCase(Context &context, const char *name, |
| const char *description, uint32_t texFormat, |
| SizeType sizeType, uint32_t filter, |
| SamplingFunction samplingFunction) |
| : TextureBorderClampTest(context, name, description, texFormat, tcu::Sampler::MODE_DEPTH, |
| TextureBorderClampTest::STATE_TEXTURE_PARAM, (sizeType == SIZE_POT) ? (32) : (13), |
| (sizeType == SIZE_POT) ? (16) : (17), samplingFunction, FLAG_USE_SHADOW_SAMPLER) |
| , m_filter(filter) |
| { |
| } |
| |
| void TextureBorderClampDepthCompareCase::init(void) |
| { |
| TextureBorderClampTest::init(); |
| |
| // 0.5 <= 0.7 |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.15f, -0.35f); |
| iteration.p1 = tcu::Vec2(1.25f, 1.1f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(0.7f, 0.0f, 0.0f, 0.0f)); |
| iteration.description = "Border color in [0, 1] range"; |
| iteration.compareMode = GL_LEQUAL; |
| iteration.compareRef = 0.5f; |
| m_iterations.push_back(iteration); |
| } |
| |
| // 1.5 <= 1.0 |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.15f, -0.35f); |
| iteration.p1 = tcu::Vec2(1.25f, 1.1f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(1.5f, 0.0f, 0.0f, 0.0f)); |
| iteration.description = "Border color > 1, should be clamped"; |
| iteration.compareMode = GL_LEQUAL; |
| iteration.compareRef = 1.0f; |
| m_iterations.push_back(iteration); |
| } |
| |
| // -0.5 >= 0.0 |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.15f, -0.35f); |
| iteration.p1 = tcu::Vec2(1.25f, 1.1f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(-0.5f, 0.0f, 0.0f, 0.0f)); |
| iteration.description = "Border color < 0, should be clamped"; |
| iteration.compareMode = GL_GEQUAL; |
| iteration.compareRef = 0.0f; |
| m_iterations.push_back(iteration); |
| } |
| |
| // inf < 1.25 |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.15f, -0.35f); |
| iteration.p1 = tcu::Vec2(1.25f, 1.1f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f)); |
| iteration.description = "Border color == inf, should be clamped; ref > 1"; |
| iteration.compareMode = GL_LESS; |
| iteration.compareRef = 1.25f; |
| m_iterations.push_back(iteration); |
| } |
| |
| // -inf > -0.5 |
| { |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.15f, -0.35f); |
| iteration.p1 = tcu::Vec2(1.25f, 1.1f); |
| iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f)); |
| iteration.description = "Border color == inf, should be clamped; ref < 0"; |
| iteration.compareMode = GL_GREATER; |
| iteration.compareRef = -0.5f; |
| m_iterations.push_back(iteration); |
| } |
| |
| // common parameters |
| for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) |
| { |
| IterationConfig &iteration = m_iterations[ndx]; |
| |
| iteration.lookupScale = tcu::Vec4(1.0); |
| iteration.lookupBias = tcu::Vec4(0.0); |
| iteration.minFilter = m_filter; |
| iteration.magFilter = m_filter; |
| iteration.sWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.tWrapMode = GL_CLAMP_TO_BORDER; |
| } |
| } |
| |
| int TextureBorderClampDepthCompareCase::getNumIterations(void) const |
| { |
| return (int)m_iterations.size(); |
| } |
| |
| TextureBorderClampTest::IterationConfig TextureBorderClampDepthCompareCase::getIteration(int ndx) const |
| { |
| return m_iterations[ndx]; |
| } |
| |
| class TextureBorderClampUnusedChannelCase : public TextureBorderClampTest |
| { |
| public: |
| TextureBorderClampUnusedChannelCase(Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode depthStencilMode); |
| |
| private: |
| void init(void); |
| |
| int getNumIterations(void) const; |
| IterationConfig getIteration(int ndx) const; |
| |
| std::vector<IterationConfig> m_iterations; |
| }; |
| |
| TextureBorderClampUnusedChannelCase::TextureBorderClampUnusedChannelCase( |
| Context &context, const char *name, const char *description, uint32_t texFormat, |
| tcu::Sampler::DepthStencilMode depthStencilMode) |
| : TextureBorderClampTest(context, name, description, texFormat, depthStencilMode, |
| TextureBorderClampTest::STATE_TEXTURE_PARAM, 8, 8, SAMPLE_FILTER) |
| { |
| } |
| |
| static rr::GenericVec4 selectComponents(const rr::GenericVec4 &trueComponents, const rr::GenericVec4 &falseComponents, |
| const tcu::BVec4 &m) |
| { |
| return rr::GenericVec4(tcu::select(trueComponents.get<uint32_t>(), falseComponents.get<uint32_t>(), m)); |
| } |
| |
| void TextureBorderClampUnusedChannelCase::init(void) |
| { |
| TextureBorderClampTest::init(); |
| |
| // \note TextureBorderClampTest::init() creates texture |
| const tcu::TextureFormat texFormat = |
| tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); |
| const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(texFormat); |
| const float maxChannelValue = (channelMask[0]) ? (texFormatInfo.valueMax[0]) : |
| (channelMask[1]) ? (texFormatInfo.valueMax[1]) : |
| (channelMask[2]) ? (texFormatInfo.valueMax[2]) : |
| (texFormatInfo.valueMax[3]); |
| |
| const rr::GenericVec4 effectiveColors = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.6f)); |
| rr::GenericVec4 nonEffectiveColors; |
| |
| switch (m_channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f)); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<int32_t>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<uint32_t>()); |
| break; |
| default: |
| DE_ASSERT(false); |
| } |
| |
| IterationConfig iteration; |
| iteration.p0 = tcu::Vec2(-0.25f, -0.75f); |
| iteration.p1 = tcu::Vec2(2.25f, 1.25f); |
| iteration.borderColor = selectComponents(effectiveColors, nonEffectiveColors, channelMask); |
| iteration.lookupScale = texFormatInfo.lookupScale; |
| iteration.lookupBias = texFormatInfo.lookupBias; |
| iteration.minFilter = GL_NEAREST; |
| iteration.magFilter = GL_NEAREST; |
| iteration.sWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.tWrapMode = GL_CLAMP_TO_BORDER; |
| iteration.compareMode = GL_NONE; |
| iteration.compareRef = 0.0f; |
| iteration.description = "Setting values to unused border color components"; |
| |
| m_iterations.push_back(iteration); |
| } |
| |
| int TextureBorderClampUnusedChannelCase::getNumIterations(void) const |
| { |
| return (int)m_iterations.size(); |
| } |
| |
| TextureBorderClampTest::IterationConfig TextureBorderClampUnusedChannelCase::getIteration(int ndx) const |
| { |
| return m_iterations[ndx]; |
| } |
| |
| class TextureBorderClampPerAxisCase3D : public TestCase |
| { |
| public: |
| TextureBorderClampPerAxisCase3D(Context &context, const char *name, const char *description, uint32_t texFormat, |
| SizeType size, uint32_t filter, uint32_t sWrap, uint32_t tWrap, uint32_t rWrap); |
| |
| private: |
| void init(void); |
| void deinit(void); |
| IterateResult iterate(void); |
| |
| void renderTo(tcu::Surface &surface, const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| void logParams(const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| void verifyImage(const tcu::Surface &image, const glu::TextureTestUtil::ReferenceParams &samplerParams); |
| |
| glu::TextureTestUtil::ReferenceParams getSamplerParams(void) const; |
| uint32_t getCaseSeed(void) const; |
| |
| enum |
| { |
| VIEWPORT_WIDTH = 128, |
| VIEWPORT_HEIGHT = 128, |
| }; |
| |
| const uint32_t m_texFormat; |
| const tcu::TextureChannelClass m_channelClass; |
| const tcu::IVec3 m_size; |
| const uint32_t m_filter; |
| const uint32_t m_sWrap; |
| const uint32_t m_tWrap; |
| const uint32_t m_rWrap; |
| |
| de::MovePtr<glu::Texture3D> m_texture; |
| de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer; |
| |
| rr::GenericVec4 m_borderColor; |
| std::vector<float> m_texCoords; |
| tcu::Vec4 m_lookupScale; |
| tcu::Vec4 m_lookupBias; |
| }; |
| |
| TextureBorderClampPerAxisCase3D::TextureBorderClampPerAxisCase3D(Context &context, const char *name, |
| const char *description, uint32_t texFormat, |
| SizeType size, uint32_t filter, uint32_t sWrap, |
| uint32_t tWrap, uint32_t rWrap) |
| : TestCase(context, name, description) |
| , m_texFormat(texFormat) |
| , m_channelClass(getFormatChannelClass(texFormat, tcu::Sampler::MODE_LAST)) |
| , m_size((size == SIZE_POT) ? (tcu::IVec3(8, 16, 4)) : (tcu::IVec3(13, 5, 7))) |
| , m_filter(filter) |
| , m_sWrap(sWrap) |
| , m_tWrap(tWrap) |
| , m_rWrap(rWrap) |
| { |
| } |
| |
| void TextureBorderClampPerAxisCase3D::init(void) |
| { |
| auto ctxType = m_context.getRenderContext().getType(); |
| const bool isES32orGL45 = glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) || |
| glu::contextSupports(ctxType, glu::ApiType::core(4, 5)); |
| const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(ctxType); |
| |
| if (!isES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp")) |
| throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension"); |
| |
| if (glu::isCompressedFormat(m_texFormat) && !isES32orGL45 && |
| tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) && |
| !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr")) |
| { |
| throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension"); |
| } |
| if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888")) |
| throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension"); |
| if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH || |
| m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT) |
| { |
| throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + |
| de::toString<int>(VIEWPORT_HEIGHT) + " viewport"); |
| } |
| |
| // resources |
| m_texture = |
| genDummyTexture<glu::Texture3D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, m_size); |
| m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer( |
| m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP)); |
| |
| // texture info |
| m_testCtx.getLog() << tcu::TestLog::Message << "Created 3D texture with format " |
| << glu::getTextureFormatName(m_texFormat) << ", size (" << m_texture->getRefTexture().getWidth() |
| << ", " << m_texture->getRefTexture().getHeight() << ", " |
| << m_texture->getRefTexture().getDepth() << ")\n" |
| << tcu::TestLog::EndMessage; |
| |
| // tex coord |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Setting tex coords bottom-left: (-1, -1, -1.5), top-right (2, 2, 2.5)\n" |
| << tcu::TestLog::EndMessage; |
| |
| m_texCoords.resize(4 * 3); |
| |
| m_texCoords[0] = -1.0f; |
| m_texCoords[1] = -1.0f; |
| m_texCoords[2] = -1.5f; |
| m_texCoords[3] = -1.0f; |
| m_texCoords[4] = 2.0f; |
| m_texCoords[5] = 0.5f; |
| m_texCoords[6] = 2.0f; |
| m_texCoords[7] = -1.0f; |
| m_texCoords[8] = 0.5f; |
| m_texCoords[9] = 2.0f; |
| m_texCoords[10] = 2.0f; |
| m_texCoords[11] = 2.5f; |
| } |
| |
| // set render params |
| { |
| const tcu::TextureFormat texFormat = m_texture->getRefTexture().getFormat(); |
| const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); |
| |
| m_borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.2f, 0.6f, 0.9f, 0.4f)); |
| |
| m_lookupScale = texFormatInfo.lookupScale; |
| m_lookupBias = texFormatInfo.lookupBias; |
| } |
| } |
| |
| void TextureBorderClampPerAxisCase3D::deinit(void) |
| { |
| m_texture.clear(); |
| m_renderer.clear(); |
| } |
| |
| TextureBorderClampPerAxisCase3D::IterateResult TextureBorderClampPerAxisCase3D::iterate(void) |
| { |
| tcu::Surface renderedFrame(VIEWPORT_WIDTH, VIEWPORT_HEIGHT); |
| const glu::TextureTestUtil::ReferenceParams samplerParams = getSamplerParams(); |
| |
| logParams(samplerParams); |
| renderTo(renderedFrame, samplerParams); |
| verifyImage(renderedFrame, samplerParams); |
| |
| return STOP; |
| } |
| |
| void TextureBorderClampPerAxisCase3D::logParams(const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const std::string borderColorString = |
| (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (de::toString(m_borderColor.get<int32_t>())) : |
| (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(m_borderColor.get<uint32_t>())) : |
| (de::toString(m_borderColor.get<float>())); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "Border color is " << borderColorString << "\n" |
| << "Texture lookup bias: " << samplerParams.colorBias << "\n" |
| << "Texture lookup scale: " << samplerParams.colorScale << "\n" |
| << "Filter: " << glu::getTextureFilterName(m_filter) << "\n" |
| << "Wrap mode: s = " << glu::getRepeatModeStr(m_sWrap) |
| << ", t = " << glu::getRepeatModeStr(m_tWrap) << ", r = " << glu::getRepeatModeStr(m_rWrap) |
| << "\n" |
| << tcu::TestLog::EndMessage; |
| } |
| |
| void TextureBorderClampPerAxisCase3D::renderTo(tcu::Surface &surface, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const glw::Functions &gl = m_context.getRenderContext().getFunctions(); |
| const gls::TextureTestUtil::RandomViewport viewport(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, |
| getCaseSeed()); |
| |
| // Bind to unit 0. |
| gl.activeTexture(GL_TEXTURE0); |
| gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture()); |
| |
| // Setup filtering and wrap modes. |
| gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); |
| gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); |
| gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glu::getGLWrapMode(samplerParams.sampler.wrapR)); |
| gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); |
| gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); |
| |
| switch (m_channelClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| gl.texParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<float>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| gl.texParameterIiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<int32_t>()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| gl.texParameterIuiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<uint32_t>()); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); |
| |
| gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); |
| m_renderer->renderQuad(0, &m_texCoords[0], samplerParams); |
| glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess()); |
| } |
| |
| void TextureBorderClampPerAxisCase3D::verifyImage(const tcu::Surface &renderedFrame, |
| const glu::TextureTestUtil::ReferenceParams &samplerParams) |
| { |
| const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); |
| const int colorErrorBits = 2; |
| const tcu::IVec4 colorBits = |
| tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); |
| tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight()); |
| tcu::LodPrecision lodPrecision; |
| tcu::LookupPrecision lookupPrecision; |
| int numFailedPixels; |
| |
| lodPrecision.derivateBits = 18; |
| lodPrecision.lodBits = 5; |
| |
| lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale; |
| lookupPrecision.coordBits = tcu::IVec3(20, 20, 0); |
| lookupPrecision.uvwBits = tcu::IVec3(5, 5, 0); |
| lookupPrecision.colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); |
| |
| glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), |
| &m_texCoords[0], samplerParams); |
| |
| numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff( |
| renderedFrame.getAccess(), reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(), |
| &m_texCoords[0], samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog()); |
| |
| if (numFailedPixels > 0) |
| m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels |
| << " invalid pixels!" << tcu::TestLog::EndMessage; |
| m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") |
| << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); |
| if (numFailedPixels > 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) |
| << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); |
| } |
| m_testCtx.getLog() << tcu::TestLog::EndImageSet; |
| |
| if (numFailedPixels == 0) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); |
| } |
| |
| glu::TextureTestUtil::ReferenceParams TextureBorderClampPerAxisCase3D::getSamplerParams(void) const |
| { |
| const tcu::TextureFormat texFormat = m_texture->getRefTexture().getFormat(); |
| glu::TextureTestUtil::ReferenceParams refParams(glu::TextureTestUtil::TEXTURETYPE_3D); |
| |
| refParams.sampler = glu::mapGLSampler(m_sWrap, m_tWrap, m_rWrap, m_filter, m_filter); |
| refParams.sampler.borderColor = m_borderColor; |
| refParams.lodMode = glu::TextureTestUtil::LODMODE_EXACT; |
| refParams.samplerType = glu::TextureTestUtil::getSamplerType(texFormat); |
| refParams.colorScale = m_lookupScale; |
| refParams.colorBias = m_lookupBias; |
| |
| return refParams; |
| } |
| |
| uint32_t TextureBorderClampPerAxisCase3D::getCaseSeed(void) const |
| { |
| tcu::SeedBuilder builder; |
| builder << std::string(getName()) << m_texFormat << m_filter << m_sWrap << m_tWrap << m_rWrap |
| << m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight() |
| << m_texture->getRefTexture().getDepth(); |
| return builder.get(); |
| } |
| |
| static bool isFormatSupported(uint32_t format, bool isGL45) |
| { |
| if (isGL45 && (format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA)) |
| return false; |
| |
| return true; |
| } |
| |
| } // namespace |
| |
| TextureBorderClampTests::TextureBorderClampTests(Context &context, bool isGL45) |
| : TestCaseGroup(context, "border_clamp", "EXT_texture_border_clamp tests") |
| , m_isGL45(isGL45) |
| { |
| } |
| |
| TextureBorderClampTests::~TextureBorderClampTests(void) |
| { |
| } |
| |
| void TextureBorderClampTests::init(void) |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t filter; |
| TextureBorderClampTest::SamplingFunction sampling; |
| } s_filters[] = { |
| {"nearest", GL_NEAREST, TextureBorderClampTest::SAMPLE_FILTER}, |
| {"linear", GL_LINEAR, TextureBorderClampTest::SAMPLE_FILTER}, |
| {"gather", GL_NEAREST, TextureBorderClampTest::SAMPLE_GATHER}, |
| }; |
| |
| // .formats |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| tcu::Sampler::DepthStencilMode mode; |
| } formats[] = { |
| {"luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST}, |
| {"alpha", GL_ALPHA, tcu::Sampler::MODE_LAST}, |
| {"luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST}, |
| {"bgra", GL_BGRA, tcu::Sampler::MODE_LAST}, |
| {"r8", GL_R8, tcu::Sampler::MODE_LAST}, |
| {"r8_snorm", GL_R8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"rg8", GL_RG8, tcu::Sampler::MODE_LAST}, |
| {"rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"rgb8", GL_RGB8, tcu::Sampler::MODE_LAST}, |
| {"rgb8_snorm", GL_RGB8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"rgb565", GL_RGB565, tcu::Sampler::MODE_LAST}, |
| {"rgba4", GL_RGBA4, tcu::Sampler::MODE_LAST}, |
| {"rgb5_a1", GL_RGB5_A1, tcu::Sampler::MODE_LAST}, |
| {"rgba8", GL_RGBA8, tcu::Sampler::MODE_LAST}, |
| {"rgba8_snorm", GL_RGBA8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"rgb10_a2", GL_RGB10_A2, tcu::Sampler::MODE_LAST}, |
| {"rgb10_a2ui", GL_RGB10_A2UI, tcu::Sampler::MODE_LAST}, |
| {"srgb8", GL_SRGB8, tcu::Sampler::MODE_LAST}, |
| {"srgb8_alpha8", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST}, |
| {"r16f", GL_R16F, tcu::Sampler::MODE_LAST}, |
| {"rg16f", GL_RG16F, tcu::Sampler::MODE_LAST}, |
| {"rgb16f", GL_RGB16F, tcu::Sampler::MODE_LAST}, |
| {"rgba16f", GL_RGBA16F, tcu::Sampler::MODE_LAST}, |
| {"r32f", GL_R32F, tcu::Sampler::MODE_LAST}, |
| {"rg32f", GL_RG32F, tcu::Sampler::MODE_LAST}, |
| {"rgb32f", GL_RGB32F, tcu::Sampler::MODE_LAST}, |
| {"rgba32f", GL_RGBA32F, tcu::Sampler::MODE_LAST}, |
| {"r11f_g11f_b10f", GL_R11F_G11F_B10F, tcu::Sampler::MODE_LAST}, |
| {"rgb9_e5", GL_RGB9_E5, tcu::Sampler::MODE_LAST}, |
| {"r8i", GL_R8I, tcu::Sampler::MODE_LAST}, |
| {"r8ui", GL_R8UI, tcu::Sampler::MODE_LAST}, |
| {"r16i", GL_R16I, tcu::Sampler::MODE_LAST}, |
| {"r16ui", GL_R16UI, tcu::Sampler::MODE_LAST}, |
| {"r32i", GL_R32I, tcu::Sampler::MODE_LAST}, |
| {"r32ui", GL_R32UI, tcu::Sampler::MODE_LAST}, |
| {"rg8i", GL_RG8I, tcu::Sampler::MODE_LAST}, |
| {"rg8ui", GL_RG8UI, tcu::Sampler::MODE_LAST}, |
| {"rg16i", GL_RG16I, tcu::Sampler::MODE_LAST}, |
| {"rg16ui", GL_RG16UI, tcu::Sampler::MODE_LAST}, |
| {"rg32i", GL_RG32I, tcu::Sampler::MODE_LAST}, |
| {"rg32ui", GL_RG32UI, tcu::Sampler::MODE_LAST}, |
| {"rgb8i", GL_RGB8I, tcu::Sampler::MODE_LAST}, |
| {"rgb8ui", GL_RGB8UI, tcu::Sampler::MODE_LAST}, |
| {"rgb16i", GL_RGB16I, tcu::Sampler::MODE_LAST}, |
| {"rgb16ui", GL_RGB16UI, tcu::Sampler::MODE_LAST}, |
| {"rgb32i", GL_RGB32I, tcu::Sampler::MODE_LAST}, |
| {"rgb32ui", GL_RGB32UI, tcu::Sampler::MODE_LAST}, |
| {"rgba8i", GL_RGBA8I, tcu::Sampler::MODE_LAST}, |
| {"rgba8ui", GL_RGBA8UI, tcu::Sampler::MODE_LAST}, |
| {"rgba16i", GL_RGBA16I, tcu::Sampler::MODE_LAST}, |
| {"rgba16ui", GL_RGBA16UI, tcu::Sampler::MODE_LAST}, |
| {"rgba32i", GL_RGBA32I, tcu::Sampler::MODE_LAST}, |
| {"rgba32ui", GL_RGBA32UI, tcu::Sampler::MODE_LAST}, |
| {"depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH}, |
| {"depth_component24", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH}, |
| {"depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH}, |
| {"stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL}, |
| {"depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST}, |
| {"compressed_signed_r11_eac", GL_COMPRESSED_SIGNED_R11_EAC, tcu::Sampler::MODE_LAST}, |
| {"compressed_rg11_eac", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST}, |
| {"compressed_signed_rg11_eac", GL_COMPRESSED_SIGNED_RG11_EAC, tcu::Sampler::MODE_LAST}, |
| {"compressed_rgb8_etc2", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST}, |
| {"compressed_srgb8_etc2", GL_COMPRESSED_SRGB8_ETC2, tcu::Sampler::MODE_LAST}, |
| {"compressed_rgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, |
| tcu::Sampler::MODE_LAST}, |
| {"compressed_srgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, |
| tcu::Sampler::MODE_LAST}, |
| {"compressed_rgba8_etc2_eac", GL_COMPRESSED_RGBA8_ETC2_EAC, tcu::Sampler::MODE_LAST}, |
| {"compressed_srgb8_alpha8_etc2_eac", GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, tcu::Sampler::MODE_LAST}, |
| }; |
| |
| tcu::TestCaseGroup *const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Format tests"); |
| addChild(formatsGroup); |
| |
| // .format |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| { |
| const uint32_t format = formats[formatNdx].format; |
| const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; |
| const bool isCompressed = glu::isCompressedFormat(format); |
| const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); |
| tcu::TestCaseGroup *const formatGroup = |
| new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); |
| |
| formatsGroup->addChild(formatGroup); |
| |
| // .nearest |
| // .linear |
| for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) |
| { |
| // [not-compressed] |
| // .size_pot |
| // .size_npot |
| // [compressed] |
| // .size_tile_multiple (also pot) |
| // .size_not_tile_multiple (also npot) |
| for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) |
| { |
| const bool isNpotCase = (sizeNdx == 1); |
| const char *const sizePotName = (!isCompressed) ? ("size_pot") : ("size_tile_multiple"); |
| const char *const sizeNpotName = (!isCompressed) ? ("size_npot") : ("size_not_tile_multiple"); |
| const char *const sizeName = (isNpotCase) ? (sizeNpotName) : (sizePotName); |
| const SizeType sizeType = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); |
| const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + sizeName; |
| const uint32_t filter = s_filters[filterNdx].filter; |
| |
| if ((coreFilterable || !filterRequiresFilterability(filter)) && isFormatSupported(format, m_isGL45)) |
| formatGroup->addChild( |
| new TextureBorderClampFormatCase(m_context, caseName.c_str(), "", format, sampleMode, |
| TextureBorderClampFormatCase::STATE_TEXTURE_PARAM, |
| sizeType, filter, s_filters[filterNdx].sampling)); |
| } |
| } |
| } |
| } |
| |
| // .range_clamp |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| tcu::Sampler::DepthStencilMode mode; |
| } formats[] = { |
| {"unorm_color", GL_R8, tcu::Sampler::MODE_LAST}, |
| {"snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"float_color", GL_RG32F, tcu::Sampler::MODE_LAST}, |
| {"int_color", GL_R8I, tcu::Sampler::MODE_LAST}, |
| {"uint_color", GL_R16UI, tcu::Sampler::MODE_LAST}, |
| {"srgb_color", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST}, |
| {"unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH}, |
| {"float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH}, |
| {"uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL}, |
| {"float_depth_uint_stencil_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"float_depth_uint_stencil_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"unorm_depth_uint_stencil_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"unorm_depth_uint_stencil_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST}, |
| }; |
| |
| tcu::TestCaseGroup *const rangeClampGroup = |
| new tcu::TestCaseGroup(m_testCtx, "range_clamp", "Range clamp tests"); |
| addChild(rangeClampGroup); |
| |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) |
| { |
| const uint32_t format = formats[formatNdx].format; |
| const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; |
| const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + formats[formatNdx].name; |
| const uint32_t filter = s_filters[filterNdx].filter; |
| const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); |
| |
| if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER) |
| continue; |
| |
| if (coreFilterable || !filterRequiresFilterability(filter)) |
| rangeClampGroup->addChild(new TextureBorderClampRangeClampCase(m_context, caseName.c_str(), "", |
| format, sampleMode, filter)); |
| } |
| } |
| |
| // .sampler |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| tcu::Sampler::DepthStencilMode mode; |
| } formats[] = { |
| {"unorm_color", GL_R8, tcu::Sampler::MODE_LAST}, |
| {"snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"float_color", GL_RG32F, tcu::Sampler::MODE_LAST}, |
| {"int_color", GL_R8I, tcu::Sampler::MODE_LAST}, |
| {"uint_color", GL_R16UI, tcu::Sampler::MODE_LAST}, |
| {"unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH}, |
| {"float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH}, |
| {"uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL}, |
| {"compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST}, |
| }; |
| |
| tcu::TestCaseGroup *const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler param tests"); |
| addChild(samplerGroup); |
| |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| { |
| const uint32_t format = formats[formatNdx].format; |
| const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; |
| const char *caseName = formats[formatNdx].name; |
| |
| samplerGroup->addChild(new TextureBorderClampFormatCase( |
| m_context, caseName, "", format, sampleMode, TextureBorderClampFormatCase::STATE_SAMPLER_PARAM, |
| SIZE_POT, GL_NEAREST, TextureBorderClampFormatCase::SAMPLE_FILTER)); |
| } |
| } |
| |
| // .per_axis_wrap_mode |
| { |
| static const struct |
| { |
| const char *name; |
| bool is3D; |
| } targets[] = { |
| {"texture_2d", false}, |
| {"texture_3d", true}, |
| }; |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| tcu::Sampler::DepthStencilMode mode; |
| bool supports3D; |
| } formats[] = { |
| {"unorm_color", GL_RG8, tcu::Sampler::MODE_LAST, true}, |
| {"snorm_color", GL_RG8_SNORM, tcu::Sampler::MODE_LAST, true}, |
| {"float_color", GL_R32F, tcu::Sampler::MODE_LAST, true}, |
| {"int_color", GL_RG16I, tcu::Sampler::MODE_LAST, true}, |
| {"uint_color", GL_R8UI, tcu::Sampler::MODE_LAST, true}, |
| {"unorm_depth", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH, false}, |
| {"float_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH, false}, |
| {"uint_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL, false}, |
| {"compressed_color", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST, false}, |
| }; |
| static const struct |
| { |
| const char *name; |
| uint32_t sWrap; |
| uint32_t tWrap; |
| uint32_t rWrap; |
| bool is3D; |
| } wrapConfigs[] = { |
| // 2d configs |
| {"s_clamp_to_edge_t_clamp_to_border", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_NONE, false}, |
| {"s_repeat_t_clamp_to_border", GL_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false}, |
| {"s_mirrored_repeat_t_clamp_to_border", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false}, |
| |
| // 3d configs |
| {"s_clamp_to_border_t_clamp_to_border_r_clamp_to_border", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, |
| GL_CLAMP_TO_BORDER, true}, |
| {"s_clamp_to_border_t_clamp_to_border_r_repeat", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, GL_REPEAT, true}, |
| {"s_mirrored_repeat_t_clamp_to_border_r_repeat", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_REPEAT, true}, |
| {"s_repeat_t_mirrored_repeat_r_clamp_to_border", GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, true}, |
| }; |
| |
| tcu::TestCaseGroup *const perAxisGroup = |
| new tcu::TestCaseGroup(m_testCtx, "per_axis_wrap_mode", "Per-axis wrapping modes"); |
| addChild(perAxisGroup); |
| |
| // .texture_nd |
| for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) |
| { |
| tcu::TestCaseGroup *const targetGroup = |
| new tcu::TestCaseGroup(m_testCtx, targets[targetNdx].name, "Texture target test"); |
| perAxisGroup->addChild(targetGroup); |
| |
| // .format |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| { |
| if (targets[targetNdx].is3D && !formats[formatNdx].supports3D) |
| continue; |
| else |
| { |
| const uint32_t format = formats[formatNdx].format; |
| const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; |
| const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); |
| tcu::TestCaseGroup *const formatGroup = |
| new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); |
| targetGroup->addChild(formatGroup); |
| |
| // .linear |
| // .nearest |
| // .gather |
| for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) |
| { |
| const uint32_t filter = s_filters[filterNdx].filter; |
| |
| if (!coreFilterable && filterRequiresFilterability(filter)) |
| { |
| // skip linear on pure integers |
| continue; |
| } |
| else if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER && |
| targets[targetNdx].is3D) |
| { |
| // skip gather on 3d |
| continue; |
| } |
| else |
| { |
| tcu::TestCaseGroup *const filteringGroup = new tcu::TestCaseGroup( |
| m_testCtx, s_filters[filterNdx].name, "Tests with specific filter"); |
| formatGroup->addChild(filteringGroup); |
| |
| // .s_XXX_t_XXX(_r_XXX) |
| for (int wrapNdx = 0; wrapNdx < DE_LENGTH_OF_ARRAY(wrapConfigs); ++wrapNdx) |
| { |
| if (wrapConfigs[wrapNdx].is3D != targets[targetNdx].is3D) |
| continue; |
| else |
| { |
| for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) |
| { |
| const char *const wrapName = wrapConfigs[wrapNdx].name; |
| const bool isNpotCase = (sizeNdx == 1); |
| const char *const sizeNameExtension = (isNpotCase) ? ("_npot") : ("_pot"); |
| const SizeType size = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); |
| |
| if (!targets[targetNdx].is3D) |
| filteringGroup->addChild(new TextureBorderClampPerAxisCase2D( |
| m_context, (std::string() + wrapName + sizeNameExtension).c_str(), "", |
| format, sampleMode, size, filter, wrapConfigs[wrapNdx].sWrap, |
| wrapConfigs[wrapNdx].tWrap, s_filters[filterNdx].sampling)); |
| else |
| { |
| DE_ASSERT(sampleMode == tcu::Sampler::MODE_LAST); |
| filteringGroup->addChild(new TextureBorderClampPerAxisCase3D( |
| m_context, (std::string() + wrapName + sizeNameExtension).c_str(), "", |
| format, size, filter, wrapConfigs[wrapNdx].sWrap, |
| wrapConfigs[wrapNdx].tWrap, wrapConfigs[wrapNdx].rWrap)); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // .depth_compare_mode |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| } formats[] = { |
| {"depth_component16", GL_DEPTH_COMPONENT16}, |
| {"depth_component24", GL_DEPTH_COMPONENT24}, |
| {"depth24_stencil8", GL_DEPTH24_STENCIL8}, |
| {"depth32f_stencil8", GL_DEPTH32F_STENCIL8}, |
| }; |
| |
| tcu::TestCaseGroup *const compareGroup = |
| new tcu::TestCaseGroup(m_testCtx, "depth_compare_mode", "Tests depth compare mode"); |
| addChild(compareGroup); |
| |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| { |
| const uint32_t format = formats[formatNdx].format; |
| tcu::TestCaseGroup *const formatGroup = |
| new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); |
| |
| compareGroup->addChild(formatGroup); |
| |
| // (format).(linear|nearest|gather)_(pot|npot) |
| for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) |
| for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) |
| { |
| const bool isNpotCase = (sizeNdx == 1); |
| const char *const sizeName = (isNpotCase) ? ("size_npot") : ("size_pot"); |
| const SizeType sizeType = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); |
| const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + sizeName; |
| const uint32_t filter = s_filters[filterNdx].filter; |
| |
| formatGroup->addChild(new TextureBorderClampDepthCompareCase( |
| m_context, caseName.c_str(), "", format, sizeType, filter, s_filters[filterNdx].sampling)); |
| } |
| } |
| } |
| |
| // unused channels (A in rgb, G in stencil etc.) |
| { |
| static const struct |
| { |
| const char *name; |
| uint32_t format; |
| tcu::Sampler::DepthStencilMode mode; |
| } formats[] = { |
| {"r8", GL_R8, tcu::Sampler::MODE_LAST}, |
| {"rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST}, |
| {"rgb8", GL_RGB8, tcu::Sampler::MODE_LAST}, |
| {"rg32f", GL_RG32F, tcu::Sampler::MODE_LAST}, |
| {"r16i", GL_RG16I, tcu::Sampler::MODE_LAST}, |
| {"luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST}, |
| {"alpha", GL_ALPHA, tcu::Sampler::MODE_LAST}, |
| {"luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST}, |
| {"depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH}, |
| {"depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH}, |
| {"stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL}, |
| {"depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH}, |
| {"depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL}, |
| {"compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST}, |
| }; |
| |
| tcu::TestCaseGroup *const unusedGroup = new tcu::TestCaseGroup( |
| m_testCtx, "unused_channels", "Tests channels that are not present in the internal format"); |
| addChild(unusedGroup); |
| |
| for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) |
| { |
| if (isFormatSupported(formats[formatNdx].format, m_isGL45)) |
| { |
| unusedGroup->addChild(new TextureBorderClampUnusedChannelCase( |
| m_context, formats[formatNdx].name, "", formats[formatNdx].format, formats[formatNdx].mode)); |
| } |
| } |
| } |
| } |
| |
| } // namespace Functional |
| } // namespace gles31 |
| } // namespace deqp |