Merge remote-tracking branch 'aosp/master' into HEAD
authorChris Forbes <chrisforbes@google.com>
Mon, 5 Feb 2018 21:10:48 +0000 (13:10 -0800)
committerChris Forbes <chrisforbes@google.com>
Mon, 5 Feb 2018 21:10:48 +0000 (13:10 -0800)
Change-Id: Iecc6b03291d94c485544ba6a270161f69fa267e3

android/cts/master/gles2-master.txt
android/cts/master/gles3-master.txt
data/gles2/shaders/declarations.test
data/gles3/shaders/declarations.test
framework/common/tcuInterval.hpp
framework/common/tcuPixelFormat.hpp
modules/egl/teglWideColorTests.cpp
modules/gles3/functional/es3fMultiviewTests.cpp
modules/glshared/glsBuiltinPrecisionTests.cpp

index 4803d8e..3e059ba 100644 (file)
@@ -1115,6 +1115,11 @@ dEQP-GLES2.functional.shaders.declarations.invalid_declarations.uniform_in_verte
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.uniform_in_fragment_main
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.varying_in_vertex_main
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.varying_in_fragment_main
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.float_partially_specified_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.float_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec2_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec3_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec4_fragment
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_vertex
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_fragment
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_xx_vertex
index f056e98..532ed06 100644 (file)
@@ -2832,6 +2832,37 @@ dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_ar
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_array_without_instance_name_2_fragment
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_in_vertex
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_in_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.float_partially_specified_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.float_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec2_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec3_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec4_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.samplerCubeShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.samplerCubeShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArray_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArrayShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArrayShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isamplerCube_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isamplerCube_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2DArray_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usamplerCube_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usamplerCube_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2DArray_fragment
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_vertex
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_fragment
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_xx_vertex
index 4dfb0a4..80c513f 100644 (file)
@@ -138,3 +138,63 @@ group invalid_declarations "Invalid declarations"
        end
 
 end # invalid_declarations
+
+group unspecified_precision "Invalid declarations with unspecified precision"
+
+       case float_partially_specified_fragment
+               expect compile_fail
+               vertex ""
+                       ${VERTEX_DECLARATIONS}
+                       void main() {}
+               ""
+               fragment ""
+                       // no global precision qualifier (e.g. precision mediump float)
+                       void main() {
+                               mediump float x = 1.0;
+                               vec3 y = vec3(x);
+                               mediump vec4 z = vec4(y, x);
+                       }
+               ""
+       end
+
+       case float_fragment
+               expect compile_fail
+               vertex ""
+                       void main() {}
+               ""
+               fragment ""
+                       void main() { float v; }
+               ""
+       end
+
+       case vec2_fragment
+               expect compile_fail
+               vertex ""
+                       void main() {}
+               ""
+               fragment ""
+                       void main() { vec2 v; }
+               ""
+       end
+
+       case vec3_fragment
+               expect compile_fail
+               vertex ""
+                       void main() {}
+               ""
+               fragment ""
+                       void main() { vec3 v; }
+               ""
+       end
+
+       case vec4_fragment
+               expect compile_fail
+               vertex ""
+                       void main() {}
+               ""
+               fragment ""
+                       void main() { vec4 v; }
+               ""
+       end
+
+end # unspecified_precision
index 86f98d9..22945c8 100644 (file)
@@ -589,3 +589,208 @@ group invalid_declarations "Invalid declarations"
        end
 
 end # invalid_declarations
+
+group unspecified_precision "Invalid declarations with unspecified precision"
+
+       case float_partially_specified_fragment
+               version 300 es
+               expect compile_fail
+               vertex ""
+                       #version 300 es
+                       ${VERTEX_DECLARATIONS}
+                       void main() {}
+               ""
+               fragment ""
+                       #version 300 es
+                       // no global precision qualifier (e.g. precision mediump float)
+                       void main() {
+                               mediump float x = 1.0;
+                               vec3 y = vec3(x);
+                               mediump vec4 z = vec4(y, x);
+                       }
+               ""
+       end
+
+       case float_fragment
+               version 300 es
+               expect compile_fail
+               vertex ""
+                       #version 300 es
+                       void main() {}
+               ""
+               fragment ""
+                       #version 300 es
+                       void main() { float v; }
+               ""
+       end
+
+       case vec2_fragment
+               version 300 es
+               expect compile_fail
+               vertex ""
+                       #version 300 es
+                       void main() {}
+               ""
+               fragment ""
+                       #version 300 es
+                       void main() { vec2 v; }
+               ""
+       end
+
+       case vec3_fragment
+               version 300 es
+               expect compile_fail
+               vertex ""
+                       #version 300 es
+                       void main() {}
+               ""
+               fragment ""
+                       #version 300 es
+                       void main() { vec3 v; }
+               ""
+       end
+
+       case vec4_fragment
+               version 300 es
+               expect compile_fail
+               vertex ""
+                       #version 300 es
+                       void main() {}
+               ""
+               fragment ""
+                       #version 300 es
+                       void main() { vec4 v; }
+               ""
+       end
+
+       case sampler3D
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform sampler3D samp;
+                       void main() {}
+               ""
+       end
+
+       case samplerCubeShadow
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform samplerCubeShadow samp;
+                       void main() {}
+               ""
+       end
+
+       case sampler2DShadow
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform sampler2DShadow samp;
+                       void main() {}
+               ""
+       end
+
+       case sampler2DArray
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform sampler2DArray samp;
+                       void main() {}
+               ""
+       end
+
+       case sampler2DArrayShadow
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform sampler2DArrayShadow samp;
+                       void main() {}
+               ""
+       end
+
+       case isampler2D
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform isampler2D samp;
+                       void main() {}
+               ""
+       end
+
+       case isampler3D
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform isampler3D samp;
+                       void main() {}
+               ""
+       end
+
+       case isamplerCube
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform isamplerCube samp;
+                       void main() {}
+               ""
+       end
+
+       case isampler2DArray
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform isampler2DArray samp;
+                       void main() {}
+               ""
+       end
+
+       case usampler2D
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform usampler2D samp;
+                       void main() {}
+               ""
+       end
+
+       case usampler3D
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform usampler3D samp;
+                       void main() {}
+               ""
+       end
+
+       case usamplerCube
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform usamplerCube samp;
+                       void main() {}
+               ""
+       end
+
+       case usampler2DArray
+               version 300 es
+               expect compile_fail
+               both ""
+                       #version 300 es
+                       uniform usampler2DArray samp;
+                       void main() {}
+               ""
+       end
+
+end # unspecified_precision
index cc271a1..bbbdf3e 100644 (file)
@@ -58,42 +58,60 @@ class Interval
 {
 public:
                                // Empty interval.
-                               Interval                (void)
-                                       : m_hasNaN      (false)
-                                       , m_lo          (TCU_INFINITY)
-                                       , m_hi          (-TCU_INFINITY) {}
+                               Interval                        (void)
+                                       : m_hasNaN              (false)
+                                       , m_lo                  (TCU_INFINITY)
+                                       , m_hi                  (-TCU_INFINITY)
+                                       , m_warningLo   (-TCU_INFINITY)
+                                       , m_warningHi   (TCU_INFINITY) {}
 
                                // Intentionally not explicit. Conversion from double to Interval is common
                                // and reasonable.
-                               Interval                (double val)
-                                       : m_hasNaN      (!!deIsNaN(val))
-                                       , m_lo          (m_hasNaN ? TCU_INFINITY : val)
-                                       , m_hi          (m_hasNaN ? -TCU_INFINITY : val) {}
+                               Interval                        (double val)
+                                       : m_hasNaN              (!!deIsNaN(val))
+                                       , m_lo                  (m_hasNaN ? TCU_INFINITY : val)
+                                       , m_hi                  (m_hasNaN ? -TCU_INFINITY : val)
+                                       , m_warningLo   (-TCU_INFINITY)
+                                       , m_warningHi   (TCU_INFINITY) {}
 
-                               Interval                (bool hasNaN_, double lo_, double hi_)
-                                       : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_) {}
+
+                               Interval(bool hasNaN_, double lo_, double hi_)
+                                       : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_), m_warningLo(-TCU_INFINITY), m_warningHi(TCU_INFINITY) {}
+
+                               Interval(bool hasNaN_, double lo_, double hi_, double wlo_, double whi_)
+                                       : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_), m_warningLo(wlo_), m_warningHi(whi_) {}
 
                                Interval                (const Interval& a, const Interval& b)
-                                       : m_hasNaN      (a.m_hasNaN || b.m_hasNaN)
-                                       , m_lo          (de::min(a.lo(), b.lo()))
-                                       , m_hi          (de::max(a.hi(), b.hi())) {}
+                                       : m_hasNaN              (a.m_hasNaN || b.m_hasNaN)
+                                       , m_lo                  (de::min(a.lo(), b.lo()))
+                                       , m_hi                  (de::max(a.hi(), b.hi()))
+                                       , m_warningLo   (de::min(a.warningLo(), b.warningLo()))
+                                       , m_warningHi   (de::max(a.warningHi(), b.warningHi())) {}
 
        double          length                  (void) const { return m_hi - m_lo; }
        double          lo                              (void) const { return m_lo; }
        double          hi                              (void) const { return m_hi; }
+       double          warningLo               (void) const { return m_warningLo; }
+       double          warningHi               (void) const { return m_warningHi; }
        bool            hasNaN                  (void) const { return m_hasNaN; }
        Interval        nan                             (void) const { return m_hasNaN ? TCU_NAN : Interval(); }
        bool            empty                   (void) const { return m_lo > m_hi; }
        bool            isFinite                (void) const { return m_lo > -TCU_INFINITY && m_hi < TCU_INFINITY; }
        bool            isOrdinary              (void) const { return !hasNaN() && !empty() && isFinite(); }
 
+       void            warning                 (double lo, double hi)
+       {
+               m_warningLo = lo;
+               m_warningHi = hi;
+       }
 
        Interval        operator|               (const Interval& other) const
        {
                return Interval(m_hasNaN || other.m_hasNaN,
                                                de::min(m_lo, other.m_lo),
-                                               de::max(m_hi, other.m_hi));
-
+                                               de::max(m_hi, other.m_hi),
+                                               de::min(m_warningLo, other.m_warningLo),
+                                               de::max(m_warningHi, other.m_warningHi));
        }
 
        Interval&       operator|=              (const Interval& other)
@@ -105,7 +123,9 @@ public:
        {
                return Interval(m_hasNaN && other.m_hasNaN,
                                                de::max(m_lo, other.m_lo),
-                                               de::min(m_hi, other.m_hi));
+                                               de::min(m_hi, other.m_hi),
+                                               de::max(m_warningLo, other.m_warningLo),
+                                               de::min(m_warningHi, other.m_warningHi));
        }
 
        Interval&       operator&=              (const Interval& other)
@@ -119,6 +139,12 @@ public:
                                (!other.hasNaN() || hasNaN()));
        }
 
+       bool            containsWarning(const Interval& other) const
+       {
+               return (other.lo() >= warningLo() && other.hi() <= warningHi() &&
+                       (!other.hasNaN() || hasNaN()));
+       }
+
        bool            intersects              (const Interval& other) const
        {
                return ((other.hi() >= lo() && other.lo() <= hi()) ||
@@ -127,7 +153,7 @@ public:
 
        Interval        operator-               (void) const
        {
-               return Interval(hasNaN(), -hi(), -lo());
+               return Interval(hasNaN(), -hi(), -lo(), -warningHi(), -warningLo());
        }
 
        static Interval unbounded       (bool nan = false)
@@ -151,6 +177,8 @@ private:
        bool            m_hasNaN;
        double          m_lo;
        double          m_hi;
+       double          m_warningLo;
+       double          m_warningHi;
 } DE_WARN_UNUSED_TYPE;
 
 inline Interval        operator+       (const Interval& x) { return x; }
index 2aa60c3..e7f9936 100644 (file)
@@ -55,6 +55,20 @@ struct PixelFormat
        {
        }
 
+       static inline int channelThreshold(int bits)
+       {
+               if (bits <= 8)
+               {
+                       // Threshold is 2^(8 - bits)
+                       return 1 << (8 - bits);
+               }
+               else
+               {
+                       // Threshold is bound by the 8-bit buffer value
+                       return 1;
+               }
+       }
+
        /*--------------------------------------------------------------------*//*!
         * \brief Get default threshold for per-pixel comparison for this format
         *
@@ -64,21 +78,33 @@ struct PixelFormat
        inline RGBA getColorThreshold (void) const
        {
                return RGBA(
-                       1 << (8 - redBits),
-                       1 << (8 - greenBits),
-                       1 << (8 - blueBits),
-                       (alphaBits > 0) ? (1 << (8 - alphaBits)) : 0);
+                       channelThreshold(redBits),
+                       channelThreshold(greenBits),
+                       channelThreshold(blueBits),
+                       alphaBits ? channelThreshold(alphaBits) : 0);
        }
 
        static inline int convertChannel (int val, int bits)
        {
-               if (bits == 1)
+               if (bits == 0)
+               {
+                       return 0;
+               }
+               else if (bits == 1)
+               {
                        return (val & 0x80) ? 0xff : 0;
+               }
+               else if (bits < 8)
+               {
+                       // Emulate precision reduction by replicating the upper bits as the fractional component
+                       int intComp   = val >> (8 - bits);
+                       int fractComp = (intComp << (24 - bits)) | (intComp << (24 - 2 * bits)) | (intComp << (24 - 3 * bits));
+                       return (intComp << (8 - bits)) | (fractComp >> (bits + 16));
+               }
                else
                {
-                       DE_ASSERT(deInRange32(bits, 4, 8));
-                       int c = val >> (8-bits);
-                       return (c << (8-bits)) | (c >> (2*bits-8));
+                       // Bits greater than or equal to 8 will have full precision, so no reduction
+                       return val;
                }
        }
 
index a54af90..ddbd4ba 100644 (file)
@@ -564,7 +564,6 @@ public:
        void                            init                                    (void);
        void                            executeTest                             (void);
        IterateResult           iterate                                 (void);
-       void                            addWindowAttributes             (const EGLint* attributes);
        void                            addTestAttributes               (const EGLint* attributes);
 
 protected:
@@ -584,7 +583,6 @@ protected:
 
 private:
        std::vector<EGLint>                                     m_attribList;
-       std::vector<EGLint>                                     m_winAttribList;
        std::vector<EGLint>                                     m_testAttribList;
        EGLConfig                                                       m_eglConfig;
        EGLint                                                          m_surfaceType;
@@ -621,18 +619,6 @@ WideColorSurfaceTest::WideColorSurfaceTest (EglTestContext& eglTestCtx, const ch
        m_attribList.push_back(EGL_NONE);
 }
 
-void WideColorSurfaceTest::addWindowAttributes(const EGLint* attributes)
-{
-       deUint32 idx = 0;
-       if (attributes == DE_NULL) return;
-
-       while (attributes[idx] != EGL_NONE)
-       {
-               m_winAttribList.push_back(attributes[idx++]);
-               m_winAttribList.push_back(attributes[idx++]);
-       }
-}
-
 void WideColorSurfaceTest::addTestAttributes(const EGLint *attributes)
 {
        deUint32 idx = 0;
@@ -1187,10 +1173,6 @@ void WideColorSurfaceTest::executeTest (void)
                        attribs.push_back(EGL_GL_COLORSPACE_KHR);
                        attribs.push_back(m_colorSpace);
                }
-               for (deUint32 i = 0; i < m_winAttribList.size(); i++)
-               {
-                       attribs.push_back(m_winAttribList[i]);
-               }
                attribs.push_back(EGL_NONE);
                attribs.push_back(EGL_NONE);
                const EGLSurface surface = egl.createPbufferSurface(m_eglDisplay, m_eglConfig, attribs.data());
@@ -1219,10 +1201,6 @@ void WideColorSurfaceTest::executeTest (void)
                        attribs.push_back(EGL_GL_COLORSPACE_KHR);
                        attribs.push_back(m_colorSpace);
                }
-               for (deUint32 i = 0; i < m_winAttribList.size(); i++)
-               {
-                       attribs.push_back(m_winAttribList[i]);
-               }
                attribs.push_back(EGL_NONE);
                attribs.push_back(EGL_NONE);
 
@@ -1243,14 +1221,6 @@ void WideColorSurfaceTest::executeTest (void)
 
                doClearTest(surface);
 
-               // If we have any window attributes, check that the values are correct
-               for (deUint32 i = 0; i < m_winAttribList.size(); i +=2)
-               {
-                       EGLint value;
-                       egl.querySurface(m_eglDisplay, surface, m_winAttribList[i], &value);
-                       TCU_CHECK(value == m_winAttribList[i+1]);
-               }
-
                if (m_testAttribList.size() > 0)
                {
                        for (deUint32 i = 0; i < m_testAttribList.size(); i +=2)
@@ -1494,24 +1464,6 @@ void HdrColorTest::executeTest (void)
        };
 
        WideColorSurfaceTest testObj(m_eglTestCtx, "window_8888_colorspace_default", "8888 window surface, default (sRGB) colorspace", windowAttribList8888, EGL_NONE, int8888Iterations);
-       const EGLint attrs[] =
-       {
-               EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, METADATA_SCALE(0.640),
-               EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, METADATA_SCALE(0.330),
-               EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, METADATA_SCALE(0.290),
-               EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, METADATA_SCALE(0.600),
-               EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, METADATA_SCALE(0.150),
-               EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, METADATA_SCALE(0.060),
-               EGL_SMPTE2086_WHITE_POINT_X_EXT, METADATA_SCALE(0.3127),
-               EGL_SMPTE2086_WHITE_POINT_Y_EXT, METADATA_SCALE(0.3290),
-               EGL_SMPTE2086_MAX_LUMINANCE_EXT, METADATA_SCALE(300.0),
-               EGL_SMPTE2086_MIN_LUMINANCE_EXT, METADATA_SCALE(0.7),
-               EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, METADATA_SCALE(300),
-               EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, METADATA_SCALE(75),
-               EGL_NONE
-       };
-
-       testObj.addWindowAttributes(attrs);
 
        const EGLint testAttrs[] =
        {
index 09cf487..fefa701 100644 (file)
@@ -188,7 +188,7 @@ void MultiviewCase::init()
 
        m_multiviewProgram = new glu::ShaderProgram(
                m_context.getRenderContext(), glu::makeVtxFragSources(multiviewVertexShader, multiviewFragmentShader));
-       DE_ASSERT(!m_multiviewProgram);
+       DE_ASSERT(m_multiviewProgram);
        if (!m_multiviewProgram->isOk())
        {
                m_testCtx.getLog() << *m_multiviewProgram;
@@ -219,7 +219,7 @@ void MultiviewCase::init()
 
        m_finalProgram = new glu::ShaderProgram(m_context.getRenderContext(),
                                                                                        glu::makeVtxFragSources(finalVertexShader, finalFragmentShader));
-       DE_ASSERT(!m_finalProgram);
+       DE_ASSERT(m_finalProgram);
        if (!m_finalProgram->isOk())
        {
                m_testCtx.getLog() << *m_finalProgram;
@@ -267,6 +267,8 @@ MultiviewCase::IterateResult MultiviewCase::iterate()
                return STOP;
        }
 
+       log << TestLog::EndSection;
+
        // Draw full screen quad into the multiview framebuffer.
        // The quad should be instanced into both layers of the array texture.
 
index 7019964..56228fb 100644 (file)
@@ -244,6 +244,13 @@ bool contains (const typename Traits<T>::IVal& ival, const T& value)
        return Traits<T>::doContains(ival, value);
 }
 
+//! Returns true iff every element of `ival` contains corresponding element of `value` within the warning interval
+template <typename T>
+bool containsWarning(const typename Traits<T>::IVal& ival, const T& value)
+{
+       return Traits<T>::doContainsWarning(ival, value);
+}
+
 //! Print out an interval with the precision of `fmt`.
 template <typename T>
 void printIVal (const FloatFormat& fmt, const typename Traits<T>::IVal& ival, ostream& os)
@@ -313,6 +320,11 @@ struct ScalarTraits
                return a.contains(double(value));
        }
 
+       static bool                     doContainsWarning(const Interval& a, T value)
+       {
+               return a.containsWarning(double(value));
+       }
+
        static Interval         doConvert               (const FloatFormat& fmt, const IVal& ival)
        {
                return fmt.convert(ival);
@@ -422,6 +434,15 @@ struct ContainerTraits
                return true;
        }
 
+       static bool                     doContainsWarning(const IVal& ival, const T& value)
+       {
+               for (int ndx = 0; ndx < T::SIZE; ++ndx)
+                       if (!containsWarning(ival[ndx], value[ndx]))
+                               return false;
+
+               return true;
+       }
+
        static void                     doPrintIVal             (const FloatFormat& fmt, const IVal ival, ostream& os)
        {
                os << "(";
@@ -492,11 +513,12 @@ struct Traits<Void>
 {
        typedef         Void                    IVal;
 
-       static Void     doMakeIVal              (const Void& value)                                             { return value; }
-       static Void     doUnion                 (const Void&, const Void&)                              { return Void(); }
-       static bool     doContains              (const Void&, Void)                                             { return true; }
-       static Void     doRound                 (const FloatFormat&, const Void& value) { return value; }
-       static Void     doConvert               (const FloatFormat&, const Void& value) { return value; }
+       static Void     doMakeIVal                      (const Void& value)                                             { return value; }
+       static Void     doUnion                         (const Void&, const Void&)                              { return Void(); }
+       static bool     doContains                      (const Void&, Void)                                             { return true; }
+       static bool     doContainsWarning       (const Void&, Void)                                             { return true; }
+       static Void     doRound                         (const FloatFormat&, const Void& value) { return value; }
+       static Void     doConvert                       (const FloatFormat&, const Void& value) { return value; }
 
        static void     doPrintValue    (const FloatFormat&, const Void&, ostream& os)
        {
@@ -1702,8 +1724,10 @@ protected:
        {
                const double    exact   = this->applyExact(arg0);
                const double    prec    = this->precision(ctx, exact, arg0);
-
-               return exact + Interval(-prec, prec);
+               const double    wprec   = this->warningPrecision(ctx, exact, arg0);
+               Interval                ioutput = exact + Interval(-prec, prec);
+               ioutput.warning(exact - wprec, exact + wprec);
+               return ioutput;
        }
 
        virtual double          applyExact              (double) const
@@ -1717,6 +1741,12 @@ protected:
        }
 
        virtual double          precision               (const EvalContext& ctx, double, double) const = 0;
+
+       virtual double  warningPrecision                (const EvalContext& ctx, double exact, double arg0) const
+       {
+               return precision(ctx, exact, arg0);
+       }
+
 };
 
 class CFloatFunc1 : public FloatFunc1
@@ -2142,6 +2172,21 @@ protected:
 
                return 0;
        }
+
+       // OpenGL API Issue #57 "Clarifying the required ULP precision for GLSL built-in log()". Agreed that
+       // implementations will be allowed 4 ULPs for HIGHP Log/Log2, but CTS should generate a quality warning.
+       double          warningPrecision(const EvalContext& ctx, double ret, double x) const
+       {
+               if (ctx.floatPrecision == glu::PRECISION_HIGHP && x > 0)
+               {
+                       return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 4.0);
+               }
+               else
+               {
+                       return precision(ctx, ret, x);
+               }
+       }
+
 };
 
 class Log2     : public LogFunc                { public: Log2  (void) : LogFunc("log2", deLog2) {} };
@@ -4693,7 +4738,10 @@ void PrecisionCase::testStatement (const Variables<In, Out>&     variables,
        // shader output to the reference.
        for (size_t valueNdx = 0; valueNdx < numValues; valueNdx++)
        {
-               bool                                            result          = true;
+               bool                                            result = true;
+               bool                                            inExpectedRange;
+               bool                                            inWarningRange;
+               const char*                                     failStr = "Fail";
                typename Traits<Out0>::IVal     reference0;
                typename Traits<Out1>::IVal     reference1;
 
@@ -4713,15 +4761,39 @@ void PrecisionCase::testStatement (const Variables<In, Out>&    variables,
                switch (outCount)
                {
                        case 2:
-                               reference1 = convert<Out1>(highpFmt, env.lookup(*variables.out1));
-                               if (!m_status.check(contains(reference1, outputs.out1[valueNdx]),
-                                                                       "Shader output 1 is outside acceptable range"))
+                               reference1      = convert<Out1>(highpFmt, env.lookup(*variables.out1));
+                               inExpectedRange = contains(reference1, outputs.out1[valueNdx]);
+                               inWarningRange  = containsWarning(reference1, outputs.out1[valueNdx]);
+                               if (!inExpectedRange && inWarningRange)
+                               {
+                                       m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 1 has low-quality shader precision");
+                                       failStr = "QualityWarning";
+                                       result = false;
+                               }
+                               else if (!inExpectedRange)
+                               {
+                                       m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 1 is outside acceptable range");
+                                       failStr = "Fail";
                                        result = false;
+                               }
+
                        case 1:
-                               reference0 = convert<Out0>(highpFmt, env.lookup(*variables.out0));
-                               if (!m_status.check(contains(reference0, outputs.out0[valueNdx]),
-                                                                       "Shader output 0 is outside acceptable range"))
+                               reference0      = convert<Out0>(highpFmt, env.lookup(*variables.out0));
+                               inExpectedRange = contains(reference0, outputs.out0[valueNdx]);
+                               inWarningRange  = containsWarning(reference0, outputs.out0[valueNdx]);
+                               if (!inExpectedRange && inWarningRange)
+                               {
+                                       m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 0 has low-quality shader precision");
+                                       failStr = "QualityWarning";
                                        result = false;
+                               }
+                               else if (!inExpectedRange)
+                               {
+                                       m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 0 is outside acceptable range");
+                                       failStr = "Fail";
+                                       result = false;
+                               }
+
                        default: break;
                }
 
@@ -4732,7 +4804,7 @@ void PrecisionCase::testStatement (const Variables<In, Out>&      variables,
                {
                        MessageBuilder  builder = log().message();
 
-                       builder << (result ? "Passed" : "Failed") << " sample:\n";
+                       builder << (result ? "Passed" : failStr) << " sample:\n";
 
                        if (inCount > 0)
                        {
@@ -4791,7 +4863,7 @@ void PrecisionCase::testStatement (const Variables<In, Out>&      variables,
        }
        else
        {
-               log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed."
+               log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed or had quality warnings."
                          << TestLog::EndMessage;
        }
 }