Update dEQP.
authorJarkko Pöyry <jpoyry@google.com>
Wed, 24 Sep 2014 17:15:01 +0000 (10:15 -0700)
committerJarkko Pöyry <jpoyry@google.com>
Wed, 24 Sep 2014 17:15:01 +0000 (10:15 -0700)
Migrate drawElements Quality Program changes from an internal repository.

Bug: 17388917

Change-Id: I754f2b4b5b077fadff210dbd8d008eeca1d5a794

15 files changed:
data/gles31/shaders/linkage_io_block.test
framework/common/tcuTextureUtil.cpp
framework/common/tcuTextureUtil.hpp
framework/delibs/cmake/toolchain-android-clang-r9d.cmake
framework/delibs/cmake/toolchain-android-r9.cmake
framework/egl/egluGLContextFactory.cpp
framework/opengl/gluRenderContext.cpp
framework/opengl/gluRenderContext.hpp
modules/gles3/functional/es3fFboColorbufferTests.cpp
modules/gles3/functional/es3fFboTestUtil.cpp
modules/gles3/functional/es3fShaderCommonFunctionTests.cpp
modules/gles31/functional/es31fShaderCommonFunctionTests.cpp
modules/gles31/functional/es31fShaderIntegerFunctionTests.cpp
modules/gles31/functional/es31fTessellationTests.cpp
modules/gles31/functional/es31fTextureGatherTests.cpp

index 1fabe66..8466a04 100644 (file)
@@ -36,7 +36,7 @@ end
 
 case mismatch_order
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block mismatch: different member declaration order"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
        expect link_fail
        vertex ""
@@ -73,7 +73,7 @@ end
 
 case mismatch_type
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block mismatch: different member type"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
        expect link_fail
        vertex ""
@@ -109,7 +109,7 @@ end
 
 case mismatch_member_name
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block mismatch: different member name"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
        expect link_fail
        vertex ""
@@ -144,7 +144,7 @@ end
 
 case mismatch_member_array_size
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block mismatch: different member array size"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
        expect link_fail
        vertex ""
@@ -177,11 +177,15 @@ case mismatch_member_array_size
        ""
 end
 
-case mismatch_with_and_without_instance_name
+case with_and_without_instance_name
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block: with and without instance name"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
-       expect link_fail
+       values
+       {
+               input float in0 = 1.0;
+               output float out0 = 1.0;
+       }
        vertex ""
                #version 310 es
                ${VERTEX_DECLARATIONS}
@@ -192,7 +196,7 @@ case mismatch_with_and_without_instance_name
 
                void main()
                {
-                       instanceName.variable = float(gl_VertexID);
+                       instanceName.variable = in0;
                        ${VERTEX_OUTPUT}
                }
        ""
@@ -207,14 +211,15 @@ case mismatch_with_and_without_instance_name
 
                void main()
                {
-                       ${FRAG_COLOR} = vec4(variable);
+                       out0 = variable;
+                       ${FRAGMENT_OUTPUT}
                }
        ""
 end
 
 case mismatch_block_array_size
        version 310 es
-       desc "Shader io block mismatch: different number of declarations"
+       desc "Shader io block mismatch: different array size"
        require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex, fragment }
        expect link_fail
        vertex ""
@@ -353,4 +358,4 @@ case ambiguous_variable_name_2
                        ${FRAG_COLOR} = vec4(variable);
                }
        ""
-end
\ No newline at end of file
+end
index abfaa15..c83d151 100644 (file)
@@ -356,6 +356,74 @@ IVec4 getTextureFormatBitDepth (const TextureFormat& format)
        return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
 }
 
+static IVec4 getChannelMantissaBitDepth (TextureFormat::ChannelType channelType)
+{
+       switch (channelType)
+       {
+               case TextureFormat::SNORM_INT8:
+               case TextureFormat::SNORM_INT16:
+               case TextureFormat::SNORM_INT32:
+               case TextureFormat::UNORM_INT8:
+               case TextureFormat::UNORM_INT16:
+               case TextureFormat::UNORM_INT32:
+               case TextureFormat::UNORM_SHORT_565:
+               case TextureFormat::UNORM_SHORT_4444:
+               case TextureFormat::UNORM_SHORT_555:
+               case TextureFormat::UNORM_SHORT_5551:
+               case TextureFormat::UNORM_INT_101010:
+               case TextureFormat::UNORM_INT_1010102_REV:
+               case TextureFormat::SIGNED_INT8:
+               case TextureFormat::SIGNED_INT16:
+               case TextureFormat::SIGNED_INT32:
+               case TextureFormat::UNSIGNED_INT8:
+               case TextureFormat::UNSIGNED_INT16:
+               case TextureFormat::UNSIGNED_INT32:
+               case TextureFormat::UNSIGNED_INT_1010102_REV:
+               case TextureFormat::UNSIGNED_INT_24_8:
+               case TextureFormat::UNSIGNED_INT_999_E5_REV:
+                       return getChannelBitDepth(channelType);
+
+               case TextureFormat::HALF_FLOAT:                                         return IVec4(10);
+               case TextureFormat::FLOAT:                                                      return IVec4(23);
+               case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:       return IVec4(6,6,5,0);
+               case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:        return IVec4(23,0,0,8);
+               default:
+                       DE_ASSERT(false);
+                       return IVec4(0);
+       }
+}
+
+IVec4 getTextureFormatMantissaBitDepth (const TextureFormat& format)
+{
+       IVec4   chnBits         = getChannelMantissaBitDepth(format.type);
+       BVec4   chnMask         = BVec4(false);
+       IVec4   chnSwz          (0,1,2,3);
+
+       switch (format.order)
+       {
+               case TextureFormat::R:          chnMask = BVec4(true,   false,  false,  false);         break;
+               case TextureFormat::A:          chnMask = BVec4(false,  false,  false,  true);          break;
+               case TextureFormat::RA:         chnMask = BVec4(true,   false,  false,  true);          break;
+               case TextureFormat::L:          chnMask = BVec4(true,   true,   true,   false);         break;
+               case TextureFormat::I:          chnMask = BVec4(true,   true,   true,   true);          break;
+               case TextureFormat::LA:         chnMask = BVec4(true,   true,   true,   true);          break;
+               case TextureFormat::RG:         chnMask = BVec4(true,   true,   false,  false);         break;
+               case TextureFormat::RGB:        chnMask = BVec4(true,   true,   true,   false);         break;
+               case TextureFormat::RGBA:       chnMask = BVec4(true,   true,   true,   true);          break;
+               case TextureFormat::BGRA:       chnMask = BVec4(true,   true,   true,   true);          chnSwz = IVec4(2, 1, 0, 3);     break;
+               case TextureFormat::ARGB:       chnMask = BVec4(true,   true,   true,   true);          chnSwz = IVec4(1, 2, 3, 0);     break;
+               case TextureFormat::sRGB:       chnMask = BVec4(true,   true,   true,   false);         break;
+               case TextureFormat::sRGBA:      chnMask = BVec4(true,   true,   true,   true);          break;
+               case TextureFormat::D:          chnMask = BVec4(true,   false,  false,  false);         break;
+               case TextureFormat::DS:         chnMask = BVec4(true,   false,  false,  true);          break;
+               case TextureFormat::S:          chnMask = BVec4(false,  false,  false,  true);          break;
+               default:
+                       DE_ASSERT(false);
+       }
+
+       return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
+}
+
 static inline float linearInterpolate (float t, float minVal, float maxVal)
 {
        return minVal + (maxVal - minVal) * t;
index c7a6bcc..72d4bcb 100644 (file)
@@ -78,8 +78,9 @@ struct TextureFormatInfo
        }
 };
 
-TextureFormatInfo      getTextureFormatInfo            (const TextureFormat& format);
-IVec4                          getTextureFormatBitDepth        (const TextureFormat& format);
+TextureFormatInfo      getTextureFormatInfo                            (const TextureFormat& format);
+IVec4                          getTextureFormatBitDepth                        (const TextureFormat& format);
+IVec4                          getTextureFormatMantissaBitDepth        (const TextureFormat& format);
 
 // Texture fill.
 void   clear                                                   (const PixelBufferAccess& access, const Vec4& color);
index 9c1b2d6..4183a8d 100644 (file)
@@ -93,6 +93,7 @@ include(CMakeForceCompiler)
 
 # Compiler binaries
 if (ANDROID_NDK_HOST_OS STREQUAL "linux-x86" OR
+       ANDROID_NDK_HOST_OS STREQUAL "linux-x86_64" OR
        ANDROID_NDK_HOST_OS STREQUAL "darwin-x86")
        cmake_force_c_compiler("${LLVM_PATH}bin/clang"                  Clang)
        cmake_force_cxx_compiler("${LLVM_PATH}bin/clang++"              Clang)
index c306721..422bb08 100644 (file)
@@ -89,6 +89,7 @@ set(LIBCPP "${ANDROID_NDK_PATH}/sources/cxx-stl/gnu-libstdc++/4.8/libs/${ANDROID
 include(CMakeForceCompiler)
 
 if (ANDROID_NDK_HOST_OS STREQUAL "linux-x86" OR
+       ANDROID_NDK_HOST_OS STREQUAL "linux-x86_64" OR
        ANDROID_NDK_HOST_OS STREQUAL "darwin-x86")
        cmake_force_c_compiler("${CROSS_COMPILE}gcc"            GNU)
        cmake_force_cxx_compiler("${CROSS_COMPILE}g++"          GNU)
index 3ab29d1..b6f79c4 100644 (file)
@@ -537,11 +537,13 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
 
        EGLU_CHECK_CALL(eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
 
+       // Init core functions
+
        if (isClientExtensionSupported(m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
        {
-               // Use eglGetProcAddress() as default
+               // Use eglGetProcAddress() for core functions
                GetProcFuncLoader funcLoader;
-               glu::initFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
+               glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
        }
 #if !defined(DEQP_GLES2_RUNTIME_LOAD)
        else if (config.type.getAPI() == glu::ApiType::es(2,0))
@@ -572,7 +574,13 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
                m_dynamicGLLibrary = new de::DynamicLibrary(libraryPath);
 
                DynamicFuncLoader funcLoader(m_dynamicGLLibrary);
-               glu::initFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
+               glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
+       }
+
+       // Init extension functions
+       {
+               GetProcFuncLoader extLoader;
+               glu::initExtensionFunctions(&m_glFunctions, &extLoader, config.type.getAPI());
        }
 
        {
index 2b380c6..9e4f9ec 100644 (file)
@@ -257,6 +257,21 @@ void initCoreFunctions (glw::Functions* dst, const glw::FunctionLoader* loader,
        throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
 }
 
+void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
+{
+       std::vector<std::string> extensions = getExtensions(*dst, apiType);
+
+       if (!extensions.empty())
+       {
+               std::vector<const char*> extStr(extensions.size());
+
+               for (size_t ndx = 0; ndx < extensions.size(); ndx++)
+                       extStr[ndx] = extensions[ndx].c_str();
+
+               initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
+       }
+}
+
 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions)
 {
        if (apiType.getProfile() == PROFILE_ES)
@@ -268,20 +283,7 @@ void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loa
 void initFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
 {
        initCoreFunctions(dst, loader, apiType);
-
-       {
-               std::vector<std::string> extensions = getExtensions(*dst, apiType);
-
-               if (!extensions.empty())
-               {
-                       std::vector<const char*> extStr(extensions.size());
-
-                       for (size_t ndx = 0; ndx < extensions.size(); ndx++)
-                               extStr[ndx] = extensions[ndx].c_str();
-
-                       initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
-               }
-       }
+       initExtensionFunctions(dst, loader, apiType);
 }
 
 } // glu
index 6465a1e..7e73172 100644 (file)
@@ -221,8 +221,10 @@ RenderContext*             createDefaultRenderContext              (tcu::Platform& platform, const tcu:
 void                           initCoreFunctions                               (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
 void                           initExtensionFunctions                  (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions);
 
-// \note initFunctions() uses glGetString* to query list of extensions, so it needs current GL context.
+// \note initFunctions() and initExtensionFunctions() without explicit extension list
+//              use glGetString* to query list of extensions, so it needs current GL context.
 void                           initFunctions                                   (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
+void                           initExtensionFunctions                  (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
 
 } // glu
 
index 64eb2a5..b1763f5 100644 (file)
@@ -632,18 +632,16 @@ protected:
 
                {
                        glu::TransferFormat             transferFmt             = glu::getTransferFormat(texFmt);
-                       bool                                    isFilterable    = glu::isGLInternalColorFormatFilterable(m_format);
                        const IVec3&                    size                    = m_texSize;
 
-
                        glGenTextures(1, &tex);
 
                        glBindTexture(GL_TEXTURE_3D,            tex);
                        glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
                        glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
                        glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_WRAP_R,              GL_CLAMP_TO_EDGE);
-                       glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_MIN_FILTER,  isFilterable ? GL_LINEAR : GL_NEAREST);
-                       glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_MAG_FILTER,  isFilterable ? GL_LINEAR : GL_NEAREST);
+                       glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_MIN_FILTER,  GL_NEAREST);
+                       glTexParameteri(GL_TEXTURE_3D,  GL_TEXTURE_MAG_FILTER,  GL_NEAREST);
                        glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
 
                        // Generate an FBO for each layer
@@ -706,7 +704,7 @@ protected:
                                glActiveTexture(GL_TEXTURE0);
                                glBindTexture(GL_TEXTURE_3D, tex);
 
-                               tdTexShader.setDepth((float(layer) + 0.5f) / float(m_texSize.z()));
+                               tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1));
                                tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
 
                                sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
index 67ed74f..78d2a5a 100644 (file)
@@ -1053,7 +1053,7 @@ static int calculateU8ConversionError (int srcBits)
 
 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
 {
-       const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(format);
+       const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
 
        return tcu::RGBA(calculateU8ConversionError(bits.x()),
                                         calculateU8ConversionError(bits.y()),
@@ -1101,7 +1101,7 @@ tcu::RGBA getToSRGBConversionThreshold (const tcu::TextureFormat& src, const tcu
        // Only SRGB8 and SRGB8_ALPHA8 formats are supported.
        DE_ASSERT(dst.type == tcu::TextureFormat::UNORM_INT8 && (dst.order == tcu::TextureFormat::sRGB || dst.order == tcu::TextureFormat::sRGBA));
 
-       const tcu::IVec4        bits            = tcu::getTextureFormatBitDepth(src);
+       const tcu::IVec4        bits            = tcu::getTextureFormatMantissaBitDepth(src);
        const bool                      dstHasAlpha     = dst.order == tcu::TextureFormat::sRGBA;
 
        return tcu::RGBA(getToSRGB8ConversionError(bits.x()),
index 86b0e40..d7c7134 100644 (file)
@@ -1216,7 +1216,6 @@ public:
        {
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
-               const bool                              hasSignedZero   = supportsSignedZero(precision);
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
 
                if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
@@ -1229,7 +1228,8 @@ public:
                                const bool              isNeg           = tcu::Float32(in0).sign() < 0;
                                const float             ref                     = isNeg ? (-float(int(-in0))) : float(int(in0));
 
-                               const deUint32  ulpDiff         = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
+                               // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
+                               const deUint32  ulpDiff         = getUlpDiffIgnoreZeroSign(out0, ref);
 
                                if (ulpDiff > 0)
                                {
index f939bd6..7327532 100644 (file)
@@ -160,6 +160,32 @@ static int getMinMantissaBits (glu::Precision precision)
        return bits[precision];
 }
 
+static int getMaxNormalizedValueExponent (glu::Precision precision)
+{
+       const int exponent[] =
+       {
+               0,              // lowp
+               13,             // mediump
+               127             // highp
+       };
+       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
+       DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
+       return exponent[precision];
+}
+
+static int getMinNormalizedValueExponent (glu::Precision precision)
+{
+       const int exponent[] =
+       {
+               -7,             // lowp
+               -13,    // mediump
+               -126    // highp
+       };
+       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
+       DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
+       return exponent[precision];
+}
+
 // CommonFunctionCase
 
 class CommonFunctionCase : public TestCase
@@ -1226,7 +1252,6 @@ public:
        {
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
-               const bool                              hasSignedZero   = supportsSignedZero(precision);
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
 
                if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
@@ -1239,7 +1264,8 @@ public:
                                const bool              isNeg           = tcu::Float32(in0).sign() < 0;
                                const float             ref                     = isNeg ? (-float(int(-in0))) : float(int(in0));
 
-                               const deUint32  ulpDiff         = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
+                               // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
+                               const deUint32  ulpDiff         = getUlpDiffIgnoreZeroSign(out0, ref);
 
                                if (ulpDiff > 0)
                                {
@@ -1909,11 +1935,15 @@ public:
                        Vec2(-1e7f,             1e7f)   // highp
                };
 
-               de::Random                              rnd                             (deStringHash(getName()) ^ 0xac23fu);
-               const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
-               const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
-               const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const float                             specialCases[][3] =
+               de::Random                              rnd                                                     (deStringHash(getName()) ^ 0xac23fu);
+               const glu::DataType             type                                            = m_spec.inputs[0].varType.getBasicType();
+               const glu::Precision    precision                                       = m_spec.inputs[0].varType.getPrecision();
+               const int                               scalarSize                                      = glu::getDataTypeScalarSize(type);
+               const int                               numMantissaBits                         = getMinMantissaBits(precision);
+               const int                               maxNormalizedValueExponent      = getMaxNormalizedValueExponent(precision);
+               const int                               minNormalizedValueExponent      = getMinNormalizedValueExponent(precision);
+               const deUint32                  representableMantissaMask       = ((deUint32(1) << numMantissaBits) - 1) << (23 - (deUint32)numMantissaBits);
+               const float                             specialCases[][3]                       =
                {
                        // a            b               c
                        { 0.0f,         0.0f,   0.0f },
@@ -1927,7 +1957,7 @@ public:
                        { -0.0f,        1.0f,   0.0f },
                        { 1.0f,         -0.0f,  0.0f }
                };
-               const int                               numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases);
+               const int                               numSpecialCases                         = DE_LENGTH_OF_ARRAY(specialCases);
 
                // Special cases
                for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
@@ -1947,6 +1977,47 @@ public:
                        for (int inputNdx = 0; inputNdx < 3; inputNdx++)
                                fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[inputNdx] + offs, numScalars);
                }
+
+               // Make sure the values are representable in the target format
+               if (precision != glu::PRECISION_HIGHP)
+               {
+                       const float     largestRepresentableValue       = tcu::Float32::constructBits(+1, maxNormalizedValueExponent, ((1u << numMantissaBits) - 1u) << (23u - (deUint32)numMantissaBits)).asFloat();
+
+                       // zero is not required to be representable, use smallest positive non-subnormal value
+                       const float zeroReplacement                             = tcu::Float32::constructBits(+1, minNormalizedValueExponent, 1).asFloat();
+
+                       for (int inputNdx = 0; inputNdx < 3; inputNdx++)
+                       {
+                               for (int caseNdx = 0; caseNdx < numValues; ++caseNdx)
+                               {
+                                       for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
+                                       {
+                                               float&                          value                                   = ((float*)values[inputNdx])[caseNdx * scalarSize + scalarNdx];
+                                               const tcu::Float32      float32Representation   (value);
+
+                                               // flush too small values to zero
+                                               if (float32Representation.exponent() < minNormalizedValueExponent)
+                                               {
+                                                       value = zeroReplacement;
+                                               }
+                                               // clamp too large values
+                                               else if (float32Representation.exponent() > maxNormalizedValueExponent)
+                                               {
+                                                       value = (float32Representation.sign() == +1) ? (largestRepresentableValue) : (-largestRepresentableValue);
+                                               }
+                                               // remove unrepresentable mantissa bits
+                                               else
+                                               {
+                                                       const tcu::Float32      targetRepresentation    (tcu::Float32::constructBits(float32Representation.sign(),
+                                                                                                                                                                                                        float32Representation.exponent(),
+                                                                                                                                                                                                        float32Representation.mantissaBits() & representableMantissaMask));
+
+                                                       value = targetRepresentation.asFloat();
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
@@ -1966,9 +2037,7 @@ public:
                        const float             res                     = ((const float*)outputs[0])[compNdx];
                        const float             ref                     = a*b + c;
 
-                       const int               numBitsLost     = precision != glu::PRECISION_HIGHP
-                                                                               ? de::max(de::max(numBitsLostInOp(a, res), numBitsLostInOp(b, res)), numBitsLostInOp(c, res))+1
-                                                                               : 1;
+                       const int               numBitsLost     = 1; // allow last bit to vary
                        const deUint32  maxUlpDiff      = getMaxUlpDiffFromBits(de::max(0, mantissaBits-numBitsLost));
 
                        const deUint32  ulpDiff         = signedZero ? getUlpDiff(res, ref) : getUlpDiffIgnoreZeroSign(res, ref);
index fc064fb..5c653dd 100644 (file)
@@ -112,11 +112,49 @@ inline int getShaderUintBitCount (glu::ShaderType shaderType, glu::Precision pre
 {
        // \todo [2013-10-31 pyry] Query from GL for vertex and fragment shaders.
        DE_UNREF(shaderType);
-       const int bitCounts[] = { 8, 16, 32 };
+       const int bitCounts[] = { 9, 16, 32 };
        DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bitCounts) == glu::PRECISION_LAST);
        return bitCounts[precision];
 }
 
+static inline deUint32 extendSignTo32 (deUint32 integer, deUint32 integerLength)
+{
+       DE_ASSERT(integerLength > 0 && integerLength <= 32);
+
+       return deUint32(0 - deInt32((integer & (1 << (integerLength - 1))) << 1)) | integer;
+}
+
+static inline deUint32 getLowBitMask (int integerLength)
+{
+       DE_ASSERT(integerLength >= 0 && integerLength <= 32);
+
+       // \note: shifting more or equal to 32 => undefined behavior. Avoid it by shifting in two parts (1 << (num-1) << 1)
+       if (integerLength == 0u)
+               return 0u;
+       return ((1u << ((deUint32)integerLength - 1u)) << 1u) - 1u;
+}
+
+static void generateRandomInputData (de::Random& rnd, glu::ShaderType shaderType, glu::DataType dataType, glu::Precision precision, deUint32* dst, int numValues)
+{
+       const int                               scalarSize              = glu::getDataTypeScalarSize(dataType);
+       const deUint32                  integerLength   = (deUint32)getShaderUintBitCount(shaderType, precision);
+       const deUint32                  integerMask             = getLowBitMask(integerLength);
+       const bool                              isUnsigned              = glu::isDataTypeUintOrUVec(dataType);
+
+       if (isUnsigned)
+       {
+               for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
+                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                               dst[valueNdx*scalarSize + compNdx] = rnd.getUint32() & integerMask;
+       }
+       else
+       {
+               for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
+                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                               dst[valueNdx*scalarSize + compNdx] = extendSignTo32(rnd.getUint32() & integerMask, integerLength);
+       }
+}
+
 } // anonymous
 
 // IntegerFunctionCase
@@ -329,13 +367,15 @@ public:
 
        void getInputValues (int numValues, void* const* values) const
        {
-               de::Random                              rnd                     (deStringHash(getName()) ^ 0x235facu);
-               const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-//             const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
-               deUint32*                               in0                     = (deUint32*)values[0];
-               deUint32*                               in1                     = (deUint32*)values[1];
-               int                                             valueNdx        = 0;
+               de::Random                              rnd                             (deStringHash(getName()) ^ 0x235facu);
+               const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
+               const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
+               const int                               scalarSize              = glu::getDataTypeScalarSize(type);
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  integerMask             = getLowBitMask(integerLength);
+               const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
+               deUint32*                               in0                             = (deUint32*)values[0];
+               deUint32*                               in1                             = (deUint32*)values[1];
 
                const struct
                {
@@ -353,38 +393,40 @@ public:
                        { 0xffffffffu,  0xffffffffu }
                };
 
+               // generate integers with proper bit count
                for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
                {
                        for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                        {
-                               in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
-                               in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
+                               in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
+                               in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
                        }
-
-                       valueNdx += 1;
                }
 
-               while (valueNdx < numValues)
+               // convert to signed
+               if (isSigned)
                {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                       for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
                        {
-                               in0[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-                               in1[valueNdx*scalarSize + compNdx] = rnd.getUint32();
+                               for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                               {
+                                       in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
+                                       in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
+                               }
                        }
-
-                       valueNdx += 1;
                }
+
+               generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
+               generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  cmpMasks0[]             = { 0xffu, 0xffffu, 0xffffffffu };
-               const deUint32                  cmpMasks1[]             = { 0xfffffff0u, 0xfffffff0u, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  mask0                   = cmpMasks0[precision];
-               const deUint32                  mask1                   = cmpMasks1[precision];
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  mask0                   = getLowBitMask(integerLength);
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
@@ -395,7 +437,7 @@ public:
                        const deUint32  ref0    = in0+in1;
                        const deUint32  ref1    = (deUint64(in0)+deUint64(in1)) > 0xffffffffu ? 1u : 0u;
 
-                       if (((out0&mask0) != (ref0&mask0)) || ((out1&mask1) != (ref1&mask1)))
+                       if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
                        {
                                m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
                                return false;
@@ -421,13 +463,15 @@ public:
 
        void getInputValues (int numValues, void* const* values) const
        {
-               de::Random                              rnd                     (deStringHash(getName()) ^ 0x235facu);
-               const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-//             const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
-               deUint32*                               in0                     = (deUint32*)values[0];
-               deUint32*                               in1                     = (deUint32*)values[1];
-               int                                             valueNdx        = 0;
+               de::Random                              rnd                             (deStringHash(getName()) ^ 0x235facu);
+               const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
+               const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
+               const int                               scalarSize              = glu::getDataTypeScalarSize(type);
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  integerMask             = getLowBitMask(integerLength);
+               const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
+               deUint32*                               in0                             = (deUint32*)values[0];
+               deUint32*                               in1                             = (deUint32*)values[1];
 
                const struct
                {
@@ -443,38 +487,40 @@ public:
                        { 0xffffffffu,  0xffffffffu },
                };
 
+               // generate integers with proper bit count
                for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
                {
                        for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                        {
-                               in0[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x;
-                               in1[valueNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y;
+                               in0[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].x & integerMask;
+                               in1[easyCaseNdx*scalarSize + compNdx] = easyCases[easyCaseNdx].y & integerMask;
                        }
-
-                       valueNdx += 1;
                }
 
-               while (valueNdx < numValues)
+               // convert to signed
+               if (isSigned)
                {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                       for (int easyCaseNdx = 0; easyCaseNdx < DE_LENGTH_OF_ARRAY(easyCases); easyCaseNdx++)
                        {
-                               in0[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-                               in1[valueNdx*scalarSize + compNdx] = rnd.getUint32();
+                               for (int compNdx = 0; compNdx < scalarSize; compNdx++)
+                               {
+                                       in0[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in0[easyCaseNdx*scalarSize + compNdx], integerLength);
+                                       in1[easyCaseNdx*scalarSize + compNdx] = extendSignTo32(in1[easyCaseNdx*scalarSize + compNdx], integerLength);
+                               }
                        }
-
-                       valueNdx += 1;
                }
+
+               generateRandomInputData(rnd, m_shaderType, type, precision, in0, numValues - DE_LENGTH_OF_ARRAY(easyCases));
+               generateRandomInputData(rnd, m_shaderType, type, precision, in1, numValues - DE_LENGTH_OF_ARRAY(easyCases));
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  cmpMasks0[]             = { 0xffu, 0xffffu, 0xffffffffu };
-               const deUint32                  cmpMasks1[]             = { 0xfffffff0u, 0xfffffff0u, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  mask0                   = cmpMasks0[precision];
-               const deUint32                  mask1                   = cmpMasks1[precision];
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  mask0                   = getLowBitMask(integerLength);
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
@@ -485,7 +531,7 @@ public:
                        const deUint32  ref0    = in0-in1;
                        const deUint32  ref1    = in0 >= in1 ? 0u : 1u;
 
-                       if (((out0&mask0) != (ref0&mask0)) || ((out1&mask1) != (ref1&mask1)))
+                       if (((out0&mask0) != (ref0&mask0)) || out1 != ref1)
                        {
                                m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(ref0) << ", " << tcu::toHex(ref1);
                                return false;
@@ -695,27 +741,22 @@ public:
                de::Random                              rnd                     (deStringHash(getName()) ^ 0xa113fca2u);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
                const bool                              ignoreSign      = precision != glu::PRECISION_HIGHP && glu::isDataTypeIntOrIVec(type);
                const int                               numBits         = getShaderUintBitCount(m_shaderType, precision) - (ignoreSign ? 1 : 0);
                deUint32*                               inValue         = (deUint32*)values[0];
                int*                                    inOffset        = (int*)values[1];
                int*                                    inBits          = (int*)values[2];
-               int                                             valueNdx        = 0;
 
-               while (valueNdx < numValues)
+               for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
                {
                        const int               bits    = rnd.getInt(0, numBits);
                        const int               offset  = rnd.getInt(0, numBits-bits);
 
                        inOffset[valueNdx]      = offset;
                        inBits[valueNdx]        = bits;
-
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                               inValue[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-
-                       valueNdx += 1;
                }
+
+               generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
@@ -731,7 +772,7 @@ public:
                        const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
                        const deUint32  out             = ((const deUint32*)outputs[0])[compNdx];
                        const deUint32  valMask = (bits == 32 ? ~0u : ((1u<<bits)-1u));
-                       const deUint32  baseVal = (value >> offset) & valMask;
+                       const deUint32  baseVal = (offset == 32) ? (0) : ((value >> offset) & valMask);
                        const deUint32  ref             = baseVal | ((isSigned && (baseVal & (1<<(bits-1)))) ? ~valMask : 0u);
 
                        if (out != ref)
@@ -764,39 +805,32 @@ public:
                de::Random                              rnd                     (deStringHash(getName()) ^ 0x12c2acff);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
                const int                               numBits         = getShaderUintBitCount(m_shaderType, precision);
                deUint32*                               inBase          = (deUint32*)values[0];
                deUint32*                               inInsert        = (deUint32*)values[1];
                int*                                    inOffset        = (int*)values[2];
                int*                                    inBits          = (int*)values[3];
-               int                                             valueNdx        = 0;
 
-               while (valueNdx < numValues)
+               for (int valueNdx = 0; valueNdx < numValues; ++valueNdx)
                {
-                       const int               bits    = rnd.getInt(0, numBits);
-                       const int               offset  = rnd.getInt(0, numBits-bits);
+                       const int bits          = rnd.getInt(0, numBits);
+                       const int offset        = rnd.getInt(0, numBits-bits);
 
                        inOffset[valueNdx]      = offset;
                        inBits[valueNdx]        = bits;
-
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                       {
-                               inBase[valueNdx*scalarSize + compNdx]   = rnd.getUint32();
-                               inInsert[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-                       }
-
-                       valueNdx += 1;
                }
+
+               generateRandomInputData(rnd, m_shaderType, type, precision, inBase, numValues);
+               generateRandomInputData(rnd, m_shaderType, type, precision, inInsert, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  cmpMasks[]              = { 0xffu, 0xffffu, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  cmpMask                 = cmpMasks[precision];
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  cmpMask                 = getLowBitMask(integerLength);
                const int                               offset                  = *((const int*)inputs[2]);
                const int                               bits                    = *((const int*)inputs[3]);
 
@@ -844,26 +878,19 @@ public:
        {
                de::Random                              rnd                     (deStringHash(getName()) ^ 0xff23a4);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
+               const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
                deUint32*                               inValue         = (deUint32*)values[0];
-               int                                             valueNdx        = 0;
 
-               while (valueNdx < numValues)
-               {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                               inValue[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-
-                       valueNdx += 1;
-               }
+               generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  cmpMasks[]              = { 0xff000000u, 0xffff0000u, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  cmpMask                 = cmpMasks[precision];
+               const deUint32                  cmpMask                 = reverseBits(getLowBitMask(integerLength));
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
@@ -900,26 +927,19 @@ public:
        {
                de::Random                              rnd                     (deStringHash(getName()) ^ 0xab2cca4);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
+               const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
                deUint32*                               inValue         = (deUint32*)values[0];
-               int                                             valueNdx        = 0;
-
-               while (valueNdx < numValues)
-               {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                               inValue[valueNdx*scalarSize + compNdx] = rnd.getUint32();
 
-                       valueNdx += 1;
-               }
+               generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  countMasks[]    = { 0xffu, 0xffffu, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  countMask               = countMasks[precision];
+               const deUint32                  countMask               = getLowBitMask(integerLength);
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
@@ -967,26 +987,19 @@ public:
        {
                de::Random                              rnd                     (deStringHash(getName()) ^ 0x9923c2af);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
+               const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
                deUint32*                               inValue         = (deUint32*)values[0];
-               int                                             valueNdx        = 0;
-
-               while (valueNdx < numValues)
-               {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                               inValue[valueNdx*scalarSize + compNdx] = rnd.getUint32();
 
-                       valueNdx += 1;
-               }
+               generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
        {
-               const deUint32                  masks[]                 = { 0xffu, 0xffffu, 0xffffffffu };
                const glu::DataType             type                    = m_spec.inputs[0].varType.getBasicType();
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
-               const deUint32                  mask                    = masks[precision];
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
+               const deUint32                  mask                    = getLowBitMask(integerLength);
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
@@ -1006,7 +1019,7 @@ public:
        }
 };
 
-static int findMSB (int value)
+static int findMSB (deInt32 value)
 {
        if (value > 0)
                return 31 - deClz32((deUint32)value);
@@ -1024,30 +1037,14 @@ static int findMSB (deUint32 value)
                return -1;
 }
 
-static int toPrecision (deUint32 value, glu::Precision precision)
+static deUint32 toPrecision (deUint32 value, int numIntegerBits)
 {
-       switch (precision)
-       {
-               case glu::PRECISION_LOWP:               return value&0xffu;
-               case glu::PRECISION_MEDIUMP:    return value&0xffffu;
-               case glu::PRECISION_HIGHP:              return value;
-               default:
-                       DE_ASSERT(false);
-                       return 0;
-       }
+       return value & getLowBitMask(numIntegerBits);
 }
 
-static int toPrecision (int value, glu::Precision precision)
+static deInt32 toPrecision (deInt32 value, int numIntegerBits)
 {
-       switch (precision)
-       {
-               case glu::PRECISION_LOWP:               return (deInt8)value;
-               case glu::PRECISION_MEDIUMP:    return (deInt16)value;
-               case glu::PRECISION_HIGHP:              return value;
-               default:
-                       DE_ASSERT(false);
-                       return 0;
-       }
+       return (deInt32)extendSignTo32((deUint32)value & getLowBitMask(numIntegerBits), numIntegerBits);
 }
 
 class FindMSBCase : public IntegerFunctionCase
@@ -1068,17 +1065,10 @@ public:
        {
                de::Random                              rnd                     (deStringHash(getName()) ^ 0x742ac4e);
                const glu::DataType             type            = m_spec.inputs[0].varType.getBasicType();
-               const int                               scalarSize      = glu::getDataTypeScalarSize(type);
+               const glu::Precision    precision       = m_spec.inputs[0].varType.getPrecision();
                deUint32*                               inValue         = (deUint32*)values[0];
-               int                                             valueNdx        = 0;
 
-               while (valueNdx < numValues)
-               {
-                       for (int compNdx = 0; compNdx < scalarSize; compNdx++)
-                               inValue[valueNdx*scalarSize + compNdx] = rnd.getUint32();
-
-                       valueNdx += 1;
-               }
+               generateRandomInputData(rnd, m_shaderType, type, precision, inValue, numValues);
        }
 
        bool compare (const void* const* inputs, const void* const* outputs)
@@ -1087,13 +1077,14 @@ public:
                const glu::Precision    precision               = m_spec.inputs[0].varType.getPrecision();
                const bool                              isSigned                = glu::isDataTypeIntOrIVec(type);
                const int                               scalarSize              = glu::getDataTypeScalarSize(type);
+               const int                               integerLength   = getShaderUintBitCount(m_shaderType, precision);
 
                for (int compNdx = 0; compNdx < scalarSize; compNdx++)
                {
                        const deUint32  value   = ((const deUint32*)inputs[0])[compNdx];
-                       const int               out             = ((const int*)outputs[0])[compNdx];
-                       const int               minRef  = isSigned ? findMSB(toPrecision(int(value), precision))        : findMSB(toPrecision(value, precision));
-                       const int               maxRef  = isSigned ? findMSB(int(value))                                                        : findMSB(value);
+                       const int               out             = ((const deInt32*)outputs[0])[compNdx];
+                       const int               minRef  = isSigned ? findMSB(toPrecision(deInt32(value), integerLength))        : findMSB(toPrecision(value, integerLength));
+                       const int               maxRef  = isSigned ? findMSB(deInt32(value))                                                            : findMSB(value);
 
                        if (!de::inRange(out, minRef, maxRef))
                        {
index adc94a8..5743788 100644 (file)
@@ -5902,7 +5902,7 @@ void UserDefinedIOCase::init (void)
 
                tesDeclarations += de::toString(glu::declare(structType)) + ";\n";
                tesStatements += "\tbool allOk = true;\n"
-                                                "\thighp uint firstFailedInputIndex = 0;\n"
+                                                "\thighp uint firstFailedInputIndex = 0u;\n"
                                                 "\t{\n"
                                                 "\t\thighp float v = 1.3;\n";
                for (int tesInputNdx = 0; tesInputNdx < (int)m_tesInputs.size(); tesInputNdx++)
index 710cadd..78dc85d 100644 (file)
@@ -163,12 +163,100 @@ static std::ostream& operator<< (std::ostream& stream, TextureSwizzleComponent c
        }
 }
 
-typedef tcu::Vector<TextureSwizzleComponent, 4> TextureSwizzle;
+struct MaybeTextureSwizzle
+{
+public:
+       static MaybeTextureSwizzle                                              createNoneTextureSwizzle        (void);
+       static MaybeTextureSwizzle                                              createSomeTextureSwizzle        (void);
+
+       bool                                                                                    isSome                                          (void) const;
+       bool                                                                                    isNone                                          (void) const;
+       bool                                                                                    isIdentitySwizzle                       (void) const;
+
+       tcu::Vector<TextureSwizzleComponent, 4>&                getSwizzle                                      (void);
+       const tcu::Vector<TextureSwizzleComponent, 4>&  getSwizzle                                      (void) const;
+
+private:
+                                                                                                       MaybeTextureSwizzle                     (void);
 
-static const TextureSwizzle s_identityTextureSwizzle(TEXTURESWIZZLECOMPONENT_R,
-                                                                                                        TEXTURESWIZZLECOMPONENT_G,
-                                                                                                        TEXTURESWIZZLECOMPONENT_B,
-                                                                                                        TEXTURESWIZZLECOMPONENT_A);
+       tcu::Vector<TextureSwizzleComponent, 4>                 m_swizzle;
+       bool                                                                                    m_isSome;
+};
+
+static std::ostream& operator<< (std::ostream& stream, const MaybeTextureSwizzle& comp)
+{
+       if (comp.isNone())
+               stream << "[default swizzle state]";
+       else
+               stream << "(" << comp.getSwizzle()[0]
+                          << ", " << comp.getSwizzle()[1]
+                          << ", " << comp.getSwizzle()[2]
+                          << ", " << comp.getSwizzle()[3]
+                          << ")";
+
+       return stream;
+}
+
+MaybeTextureSwizzle MaybeTextureSwizzle::createNoneTextureSwizzle (void)
+{
+       MaybeTextureSwizzle swizzle;
+
+       swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_LAST;
+       swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_LAST;
+       swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_LAST;
+       swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_LAST;
+       swizzle.m_isSome = false;
+
+       return swizzle;
+}
+
+MaybeTextureSwizzle MaybeTextureSwizzle::createSomeTextureSwizzle (void)
+{
+       MaybeTextureSwizzle swizzle;
+
+       swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_R;
+       swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_G;
+       swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_B;
+       swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_A;
+       swizzle.m_isSome = true;
+
+       return swizzle;
+}
+
+bool MaybeTextureSwizzle::isSome (void) const
+{
+       return m_isSome;
+}
+
+bool MaybeTextureSwizzle::isNone (void) const
+{
+       return !m_isSome;
+}
+
+bool MaybeTextureSwizzle::isIdentitySwizzle (void) const
+{
+       return  m_isSome                                                                        &&
+                       m_swizzle[0] == TEXTURESWIZZLECOMPONENT_R       &&
+                       m_swizzle[1] == TEXTURESWIZZLECOMPONENT_G       &&
+                       m_swizzle[2] == TEXTURESWIZZLECOMPONENT_B       &&
+                       m_swizzle[3] == TEXTURESWIZZLECOMPONENT_A;
+}
+
+tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void)
+{
+       return m_swizzle;
+}
+
+const tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void) const
+{
+       return m_swizzle;
+}
+
+MaybeTextureSwizzle::MaybeTextureSwizzle (void)
+       : m_swizzle     (TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST)
+       , m_isSome      (false)
+{
+}
 
 static deUint32 getGLTextureSwizzleComponent (TextureSwizzleComponent c)
 {
@@ -200,16 +288,18 @@ static inline T swizzleColorChannel (const tcu::Vector<T, 4>& src, TextureSwizzl
 }
 
 template <typename T>
-static inline tcu::Vector<T, 4> swizzleColor (const tcu::Vector<T, 4>& src, const TextureSwizzle& swizzle)
+static inline tcu::Vector<T, 4> swizzleColor (const tcu::Vector<T, 4>& src, const MaybeTextureSwizzle& swizzle)
 {
+       DE_ASSERT(swizzle.isSome());
+
        tcu::Vector<T, 4> result;
        for (int i = 0; i < 4; i++)
-               result[i] = swizzleColorChannel(src, swizzle[i]);
+               result[i] = swizzleColorChannel(src, swizzle.getSwizzle()[i]);
        return result;
 }
 
 template <typename T>
-static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const TextureSwizzle& swizzle)
+static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
 {
        DE_ASSERT(dst.getWidth()  == src.getWidth()  &&
                          dst.getHeight() == src.getHeight() &&
@@ -220,13 +310,13 @@ static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferA
                dst.setPixel(swizzleColor(src.getPixelT<T>(x, y, z), swizzle), x, y, z);
 }
 
-static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const TextureSwizzle& swizzle)
+static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
 {
        if (isDepthFormat(dst.getFormat()))
-       {
-               DE_ASSERT(swizzle == s_identityTextureSwizzle);
+               DE_ASSERT(swizzle.isNone() || swizzle.isIdentitySwizzle());
+
+       if (swizzle.isNone() || swizzle.isIdentitySwizzle())
                tcu::copy(dst, src);
-       }
        else if (isUnormFormatType(dst.getFormat().type))
                swizzlePixels<float>(dst, src, swizzle);
        else if (isUIntFormatType(dst.getFormat().type))
@@ -237,7 +327,7 @@ static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferA
                DE_ASSERT(false);
 }
 
-static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, const TextureSwizzle& swizzle)
+static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, const MaybeTextureSwizzle& swizzle)
 {
        dst = tcu::Texture2D(src.getFormat(), src.getWidth(), src.getHeight());
        for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
@@ -249,7 +339,7 @@ static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, cons
        }
 }
 
-static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray& src, const TextureSwizzle& swizzle)
+static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray& src, const MaybeTextureSwizzle& swizzle)
 {
        dst = tcu::Texture2DArray(src.getFormat(), src.getWidth(), src.getHeight(), src.getNumLayers());
        for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
@@ -261,7 +351,7 @@ static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray&
        }
 }
 
-static void swizzleTexture (tcu::TextureCube& dst, const tcu::TextureCube& src, const TextureSwizzle& swizzle)
+static void swizzleTexture (tcu::TextureCube& dst, const tcu::TextureCube& src, const MaybeTextureSwizzle& swizzle)
 {
        dst = tcu::TextureCube(src.getFormat(), src.getSize());
        for (int faceI = 0; faceI < tcu::CUBEFACE_LAST; faceI++)
@@ -825,7 +915,7 @@ public:
                                                                                                                                 tcu::Sampler::CompareMode      shadowCompareMode, //!< Should be COMPAREMODE_NONE iff textureFormat is a depth format.
                                                                                                                                 tcu::Sampler::WrapMode         wrapS,
                                                                                                                                 tcu::Sampler::WrapMode         wrapT,
-                                                                                                                                const TextureSwizzle&          texSwizzle,
+                                                                                                                                const MaybeTextureSwizzle&     texSwizzle,
                                                                                                                                 // \note Filter modes have no effect on gather (except when it comes to
                                                                                                                                 //               texture completeness); these are supposed to test just that.
                                                                                                                                 tcu::Sampler::FilterMode       minFilter,
@@ -859,7 +949,7 @@ protected:
        const tcu::Sampler::CompareMode         m_shadowCompareMode;
        const tcu::Sampler::WrapMode            m_wrapS;
        const tcu::Sampler::WrapMode            m_wrapT;
-       const TextureSwizzle                            m_textureSwizzle;
+       const MaybeTextureSwizzle                       m_textureSwizzle;
        const tcu::Sampler::FilterMode          m_minFilter;
        const tcu::Sampler::FilterMode          m_magFilter;
        const int                                                       m_baseLevel;
@@ -901,7 +991,7 @@ TextureGatherCase::TextureGatherCase (Context&                                              context,
                                                                          tcu::Sampler::CompareMode             shadowCompareMode, //!< Should be COMPAREMODE_NONE iff textureType == TEXTURETYPE_NORMAL.
                                                                          tcu::Sampler::WrapMode                wrapS,
                                                                          tcu::Sampler::WrapMode                wrapT,
-                                                                         const TextureSwizzle&                 textureSwizzle,
+                                                                         const MaybeTextureSwizzle&    textureSwizzle,
                                                                          tcu::Sampler::FilterMode              minFilter,
                                                                          tcu::Sampler::FilterMode              magFilter,
                                                                          int                                                   baseLevel,
@@ -1161,6 +1251,7 @@ void TextureGatherCase::init (void)
                gl.texParameteri(texTypeGL, GL_TEXTURE_COMPARE_FUNC, glu::getGLCompareFunc(m_shadowCompareMode));
        }
 
+       if (m_textureSwizzle.isSome())
        {
                const deUint32 swizzleNamesGL[4] =
                {
@@ -1169,13 +1260,11 @@ void TextureGatherCase::init (void)
                        GL_TEXTURE_SWIZZLE_B,
                        GL_TEXTURE_SWIZZLE_A
                };
-               const deUint32 initialGLTexSwizzles[4]  = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
 
                for (int i = 0; i < 4; i++)
                {
-                       const deUint32 curGLSwizzle = getGLTextureSwizzleComponent(m_textureSwizzle[i]);
-                       if (curGLSwizzle != initialGLTexSwizzles[i])
-                               gl.texParameteri(texTypeGL, swizzleNamesGL[i], curGLSwizzle);
+                       const deUint32 curGLSwizzle = getGLTextureSwizzleComponent(m_textureSwizzle.getSwizzle()[i]);
+                       gl.texParameteri(texTypeGL, swizzleNamesGL[i], curGLSwizzle);
                }
        }
 
@@ -1501,7 +1590,7 @@ public:
                                                 tcu::Sampler::CompareMode      shadowCompareMode,
                                                 tcu::Sampler::WrapMode         wrapS,
                                                 tcu::Sampler::WrapMode         wrapT,
-                                                const TextureSwizzle&          texSwizzle,
+                                                const MaybeTextureSwizzle&     texSwizzle,
                                                 tcu::Sampler::FilterMode       minFilter,
                                                 tcu::Sampler::FilterMode       magFilter,
                                                 int                                            baseLevel,
@@ -1591,7 +1680,7 @@ public:
                                                          tcu::Sampler::CompareMode             shadowCompareMode,
                                                          tcu::Sampler::WrapMode                wrapS,
                                                          tcu::Sampler::WrapMode                wrapT,
-                                                         const TextureSwizzle&                 texSwizzle,
+                                                         const MaybeTextureSwizzle&    texSwizzle,
                                                          tcu::Sampler::FilterMode              minFilter,
                                                          tcu::Sampler::FilterMode              magFilter,
                                                          int                                                   baseLevel,
@@ -1723,7 +1812,7 @@ public:
                                                   tcu::Sampler::CompareMode    shadowCompareMode,
                                                   tcu::Sampler::WrapMode               wrapS,
                                                   tcu::Sampler::WrapMode               wrapT,
-                                                  const TextureSwizzle&                texSwizzle,
+                                                  const MaybeTextureSwizzle&   texSwizzle,
                                                   tcu::Sampler::FilterMode             minFilter,
                                                   tcu::Sampler::FilterMode             magFilter,
                                                   int                                                  baseLevel,
@@ -1860,7 +1949,7 @@ static inline TextureGatherCase* makeTextureGatherCase (TextureType                                       textureT
                                                                                                                tcu::Sampler::CompareMode       shadowCompareMode,
                                                                                                                tcu::Sampler::WrapMode          wrapS,
                                                                                                                tcu::Sampler::WrapMode          wrapT,
-                                                                                                               const TextureSwizzle&           texSwizzle,
+                                                                                                               const MaybeTextureSwizzle&      texSwizzle,
                                                                                                                tcu::Sampler::FilterMode        minFilter,
                                                                                                                tcu::Sampler::FilterMode        magFilter,
                                                                                                                int                                                     baseLevel,
@@ -2034,7 +2123,7 @@ void TextureGatherTests::init (void)
                                                                const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
 
                                                                compareModeGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
-                                                                                                                                                                s_identityTextureSwizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize));
+                                                                                                                                                                MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize));
                                                        }
                                                }
                                        }
@@ -2049,18 +2138,15 @@ void TextureGatherTests::init (void)
                                                        DE_STATIC_ASSERT(TEXTURESWIZZLECOMPONENT_R == 0);
                                                        for (int swizzleCaseNdx = 0; swizzleCaseNdx < TEXTURESWIZZLECOMPONENT_LAST; swizzleCaseNdx++)
                                                        {
-                                                               TextureSwizzle  swizzle;
-                                                               string                  caseName;
+                                                               MaybeTextureSwizzle     swizzle = MaybeTextureSwizzle::createSomeTextureSwizzle();
+                                                               string                          caseName;
 
                                                                for (int i = 0; i < 4; i++)
                                                                {
-                                                                       swizzle[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
-                                                                       caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle[i]));
+                                                                       swizzle.getSwizzle()[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
+                                                                       caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle.getSwizzle()[i]));
                                                                }
 
-                                                               if (swizzle == s_identityTextureSwizzle)
-                                                                       continue; // Already tested in above cases.
-
                                                                swizzleGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format,
                                                                                                                                                         tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
                                                                                                                                                         swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, IVec3(64, 64, 3)));
@@ -2111,7 +2197,8 @@ void TextureGatherTests::init (void)
                                                                const string caseName = string() + "min_" + minFilters[minFilterNdx].name + "_mag_" + magFilters[magFilterNdx].name;
 
                                                                filterModeGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format, compareMode,
-                                                                                                                                                               tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, s_identityTextureSwizzle, minFilter, magFilter, 0, IVec3(64, 64, 3)));
+                                                                                                                                                               tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
+                                                                                                                                                               minFilter, magFilter, 0, IVec3(64, 64, 3)));
                                                        }
                                                }
 
@@ -2125,7 +2212,8 @@ void TextureGatherTests::init (void)
                                                                const tcu::Sampler::CompareMode         compareMode             = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
                                                                baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format,
                                                                                                                                                           compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
-                                                                                                                                                          s_identityTextureSwizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, baseLevel, IVec3(64, 64, 3)));
+                                                                                                                                                          MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST,
+                                                                                                                                                          baseLevel, IVec3(64, 64, 3)));
                                                        }
                                                }
 
@@ -2137,8 +2225,8 @@ void TextureGatherTests::init (void)
                                                        const tcu::Sampler::CompareMode compareMode = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
                                                        incompleteGroup->addChild(makeTextureGatherCase(textureType, m_context, "mipmap_incomplete", "", gatherType, offsetSize, format,
                                                                                                                                                        compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
-                                                                                                                                                       s_identityTextureSwizzle, tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST, 0, IVec3(64, 64, 3),
-                                                                                                                                                       true /* Mipmap-incomplete */));
+                                                                                                                                                       MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST,
+                                                                                                                                                       0, IVec3(64, 64, 3), true /* Mipmap-incomplete */));
                                                }
                                        }
                                }