Do not assume support for multisampled wide lines.
authorJarkko Pöyry <jpoyry@google.com>
Mon, 27 Apr 2015 23:20:50 +0000 (16:20 -0700)
committerJarkko Pöyry <jpoyry@google.com>
Wed, 29 Apr 2015 22:23:42 +0000 (15:23 -0700)
- Allow rasterization, interpolation, and clipping multisampled wide
  line cases to fail and report Compatibility Warning instad of
  failure.
- Allow line width verification failures in primitive bounding box
  tests (and generate compatibility warning).
- Not modiyfing helper_invocation cases since the test tolerate
  uncertain line rendering widths.

Bug: 20453464
Change-Id: Ib1ef997c5476e04a02a103f0636201ed94c9354e

modules/gles2/functional/es2fClippingTests.cpp
modules/gles2/functional/es2fRasterizationTests.cpp
modules/gles3/functional/es3fClippingTests.cpp
modules/gles3/functional/es3fRasterizationTests.cpp
modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp

index 7037d7a..71e74b0 100644 (file)
@@ -609,26 +609,28 @@ public:
        void                                                            init                                    (void);
        void                                                            testRender                              (void);
 
        void                                                            init                                    (void);
        void                                                            testRender                              (void);
 
+protected:
+       const float                                                     m_lineWidth;
+
 private:
        std::vector<ColoredLineData>            convertToColoredLines   (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd);
 
        const std::vector<ColoredLineData>      m_lines;
 private:
        std::vector<ColoredLineData>            convertToColoredLines   (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd);
 
        const std::vector<ColoredLineData>      m_lines;
-       const float                                                     m_lineWidth;
        const rr::WindowRectangle                       m_viewport;
 };
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
        const rr::WindowRectangle                       m_viewport;
 };
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
-       , m_lines                       (linesBegin, linesEnd)
        , m_lineWidth           (lineWidth)
        , m_lineWidth           (lineWidth)
+       , m_lines                       (linesBegin, linesEnd)
        , m_viewport            (viewport)
 {
 }
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
        , m_viewport            (viewport)
 {
 }
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
-       , m_lines                       (convertToColoredLines(linesBegin, linesEnd))
        , m_lineWidth           (lineWidth)
        , m_lineWidth           (lineWidth)
+       , m_lines                       (convertToColoredLines(linesBegin, linesEnd))
        , m_viewport            (viewport)
 {
 }
        , m_viewport            (viewport)
 {
 }
@@ -741,11 +743,12 @@ LineCase::LineCase (Context& context, const char* name, const char* description,
 
 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
 {
 
 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
 {
-       const int       faultyLimit = 6;
-       int                     faultyPixels;
+       const int               faultyLimit             = 6;
+       int                             faultyPixels;
 
 
-       tcu::TestLog&           log                     = m_testCtx.getLog();
-       tcu::Surface            diffMask        (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
+       const bool              isMsaa                  = m_context.getRenderTarget().getNumSamples() > 1;
+       tcu::TestLog&   log                             = m_testCtx.getLog();
+       tcu::Surface    diffMask                (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
 
        log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
        log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage;
 
        log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
        log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage;
@@ -762,7 +765,13 @@ void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess,
                        << TestLog::EndImageSet
                        << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
 
                        << TestLog::EndImageSet
                        << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
 
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               if (m_lineWidth != 1.0f && isMsaa)
+               {
+                       log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
+                       m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
+               }
+               else
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
        }
 }
 
        }
 }
 
@@ -813,7 +822,15 @@ void ColoredLineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageA
        {
                const float threshold = 0.3f;
                if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
        {
                const float threshold = 0.3f;
                if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
-                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               {
+                       if (m_lineWidth != 1.0f)
+                       {
+                               log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
+                               m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
+                       }
+                       else
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               }
        }
 }
 
        }
 }
 
index 5d46b05..d4125da 100644 (file)
@@ -305,6 +305,7 @@ private:
        const glw::GLenum               m_primitiveDrawType;
        const PrimitiveWideness m_primitiveWideness;
        bool                                    m_allIterationsPassed;
        const glw::GLenum               m_primitiveDrawType;
        const PrimitiveWideness m_primitiveWideness;
        bool                                    m_allIterationsPassed;
+       bool                                    m_multisampleRelaxationRequired;
 
        static const float              s_wideSize;
 };
 
        static const float              s_wideSize;
 };
@@ -312,12 +313,13 @@ private:
 const float BaseLineCase::s_wideSize = 5.0f;
 
 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness)
 const float BaseLineCase::s_wideSize = 5.0f;
 
 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness)
-       : BaseRenderingCase             (context, name, desc)
-       , m_iteration                   (0)
-       , m_iterationCount              (3)
-       , m_primitiveDrawType   (primitiveDrawType)
-       , m_primitiveWideness   (wideness)
-       , m_allIterationsPassed (true)
+       : BaseRenderingCase                                     (context, name, desc)
+       , m_iteration                                           (0)
+       , m_iterationCount                                      (3)
+       , m_primitiveDrawType                           (primitiveDrawType)
+       , m_primitiveWideness                           (wideness)
+       , m_allIterationsPassed                         (true)
+       , m_multisampleRelaxationRequired       (false)
 {
        DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
        m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
 {
        DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
        m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
@@ -368,6 +370,13 @@ BaseLineCase::IterateResult BaseLineCase::iterate (void)
 
                compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
 
 
                compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
 
+               // multisampled wide lines might not be supported
+               if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk)
+               {
+                       m_multisampleRelaxationRequired = true;
+                       compareOk = true;
+               }
+
                if (!compareOk)
                        m_allIterationsPassed = false;
        }
                if (!compareOk)
                        m_allIterationsPassed = false;
        }
@@ -375,7 +384,9 @@ BaseLineCase::IterateResult BaseLineCase::iterate (void)
        // result
        if (++m_iteration == m_iterationCount)
        {
        // result
        if (++m_iteration == m_iterationCount)
        {
-               if (m_allIterationsPassed)
+               if (m_allIterationsPassed && m_multisampleRelaxationRequired)
+                       m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed");
+               else if (m_allIterationsPassed)
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
@@ -1671,8 +1682,16 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                                break;
 
                        case LINEINTERPOLATION_INCORRECT:
                                break;
 
                        case LINEINTERPOLATION_INCORRECT:
-                               // line interpolation is incorrect
-                               m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
+                               if (scene.lineWidth != 1.0f && m_numSamples > 1)
+                               {
+                                       // multisampled wide lines might not be supported
+                                       m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed");
+                               }
+                               else
+                               {
+                                       // line interpolation is incorrect
+                                       m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
+                               }
                                break;
 
                        default:
                                break;
 
                        default:
index 9d8de92..5368229 100644 (file)
@@ -612,26 +612,28 @@ public:
        void                                                            init                                    (void);
        void                                                            testRender                              (void);
 
        void                                                            init                                    (void);
        void                                                            testRender                              (void);
 
+protected:
+       const float                                                     m_lineWidth;
+
 private:
        std::vector<ColoredLineData>            convertToColoredLines   (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd);
 
        const std::vector<ColoredLineData>      m_lines;
 private:
        std::vector<ColoredLineData>            convertToColoredLines   (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd);
 
        const std::vector<ColoredLineData>      m_lines;
-       const float                                                     m_lineWidth;
        const rr::WindowRectangle                       m_viewport;
 };
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
        const rr::WindowRectangle                       m_viewport;
 };
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
-       , m_lines                       (linesBegin, linesEnd)
        , m_lineWidth           (lineWidth)
        , m_lineWidth           (lineWidth)
+       , m_lines                       (linesBegin, linesEnd)
        , m_viewport            (viewport)
 {
 }
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
        , m_viewport            (viewport)
 {
 }
 
 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
        : RenderTestCase        (context, name, description)
-       , m_lines                       (convertToColoredLines(linesBegin, linesEnd))
        , m_lineWidth           (lineWidth)
        , m_lineWidth           (lineWidth)
+       , m_lines                       (convertToColoredLines(linesBegin, linesEnd))
        , m_viewport            (viewport)
 {
 }
        , m_viewport            (viewport)
 {
 }
@@ -744,11 +746,12 @@ LineCase::LineCase (Context& context, const char* name, const char* description,
 
 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
 {
 
 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
 {
-       const int       faultyLimit = 6;
-       int                     faultyPixels;
+       const int               faultyLimit             = 6;
+       int                             faultyPixels;
 
 
-       tcu::TestLog&           log                     = m_testCtx.getLog();
-       tcu::Surface            diffMask        (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
+       const bool              isMsaa                  = m_context.getRenderTarget().getNumSamples() > 1;
+       tcu::TestLog&   log                             = m_testCtx.getLog();
+       tcu::Surface    diffMask                (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
 
        log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
        log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage;
 
        log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
        log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage;
@@ -765,7 +768,13 @@ void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess,
                        << TestLog::EndImageSet
                        << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
 
                        << TestLog::EndImageSet
                        << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
 
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               if (m_lineWidth != 1.0f && isMsaa)
+               {
+                       log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
+                       m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
+               }
+               else
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
        }
 }
 
        }
 }
 
@@ -817,7 +826,15 @@ void ColoredLineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageA
        {
                const float threshold = 0.3f;
                if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
        {
                const float threshold = 0.3f;
                if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
-                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               {
+                       if (m_lineWidth != 1.0f)
+                       {
+                               log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
+                               m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
+                       }
+                       else
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
+               }
        }
 }
 
        }
 }
 
index fa3f6b9..aec11de 100644 (file)
@@ -510,18 +510,20 @@ private:
        const glw::GLenum               m_primitiveDrawType;
        const PrimitiveWideness m_primitiveWideness;
        bool                                    m_allIterationsPassed;
        const glw::GLenum               m_primitiveDrawType;
        const PrimitiveWideness m_primitiveWideness;
        bool                                    m_allIterationsPassed;
+       bool                                    m_multisampleRelaxationRequired;
        float                                   m_maxLineWidth;
        std::vector<float>              m_lineWidths;
 };
 
 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
        float                                   m_maxLineWidth;
        std::vector<float>              m_lineWidths;
 };
 
 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
-       : BaseRenderingCase             (context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
-       , m_iteration                   (0)
-       , m_iterationCount              (3)
-       , m_primitiveDrawType   (primitiveDrawType)
-       , m_primitiveWideness   (wideness)
-       , m_allIterationsPassed (true)
-       , m_maxLineWidth                (1.0f)
+       : BaseRenderingCase                                     (context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
+       , m_iteration                                           (0)
+       , m_iterationCount                                      (3)
+       , m_primitiveDrawType                           (primitiveDrawType)
+       , m_primitiveWideness                           (wideness)
+       , m_allIterationsPassed                         (true)
+       , m_multisampleRelaxationRequired       (false)
+       , m_maxLineWidth                                        (1.0f)
 {
        DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
 }
 {
        DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
 }
@@ -598,6 +600,13 @@ BaseLineCase::IterateResult BaseLineCase::iterate (void)
 
                        compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
 
 
                        compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
 
+                       // multisampled wide lines might not be supported
+                       if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk)
+                       {
+                               m_multisampleRelaxationRequired = true;
+                               compareOk = true;
+                       }
+
                        if (!compareOk)
                                m_allIterationsPassed = false;
                }
                        if (!compareOk)
                                m_allIterationsPassed = false;
                }
@@ -608,7 +617,9 @@ BaseLineCase::IterateResult BaseLineCase::iterate (void)
        // result
        if (++m_iteration == m_iterationCount)
        {
        // result
        if (++m_iteration == m_iterationCount)
        {
-               if (m_allIterationsPassed)
+               if (m_allIterationsPassed && m_multisampleRelaxationRequired)
+                       m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed");
+               else if (m_allIterationsPassed)
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
@@ -2021,8 +2032,16 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                                        break;
 
                                case LINEINTERPOLATION_INCORRECT:
                                        break;
 
                                case LINEINTERPOLATION_INCORRECT:
-                                       // line interpolation is incorrect
-                                       m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
+                                       if (scene.lineWidth != 1.0f && m_numSamples > 1)
+                                       {
+                                               // multisampled wide lines might not be supported
+                                               m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed");
+                                       }
+                                       else
+                                       {
+                                               // line interpolation is incorrect
+                                               m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
+                                       }
                                        break;
 
                                default:
                                        break;
 
                                default:
index 31c123e..58fafd9 100644 (file)
@@ -1398,6 +1398,12 @@ private:
                DIRECTION_VERTICAL,
        };
 
                DIRECTION_VERTICAL,
        };
 
+       enum ScanResult
+       {
+               SCANRESULT_NUM_LINES_OK_BIT             = (1 << 0),
+               SCANRESULT_LINE_WIDTH_OK_BIT    = (1 << 1),
+       };
+
        void                            init                                                    (void);
 
        std::string                     genVertexSource                                 (void) const;
        void                            init                                                    (void);
 
        std::string                     genVertexSource                                 (void) const;
@@ -1412,8 +1418,8 @@ private:
        void                            verifyRenderResult                              (const IterationConfig& config);
 
        tcu::IVec2                      getNumberOfLinesRange                   (int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const;
        void                            verifyRenderResult                              (const IterationConfig& config);
 
        tcu::IVec2                      getNumberOfLinesRange                   (int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const;
-       bool                            scanRow                                                 (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& floodCounter) const;
-       bool                            scanColumn                                              (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& floodCounter) const;
+       deUint8                         scanRow                                                 (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& floodCounter) const;
+       deUint8                         scanColumn                                              (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& floodCounter) const;
        bool                            checkAreaNumLines                               (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
        tcu::IVec2                      getNumMinimaMaxima                              (const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
        bool                            checkLineWidths                                 (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
        bool                            checkAreaNumLines                               (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
        tcu::IVec2                      getNumMinimaMaxima                              (const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
        bool                            checkLineWidths                                 (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
@@ -1782,6 +1788,7 @@ void LineRenderCase::renderTestPattern (const IterationConfig& config)
 void LineRenderCase::verifyRenderResult (const IterationConfig& config)
 {
        const glw::Functions&   gl                                              = m_context.getRenderContext().getFunctions();
 void LineRenderCase::verifyRenderResult (const IterationConfig& config)
 {
        const glw::Functions&   gl                                              = m_context.getRenderContext().getFunctions();
+       const bool                              isMsaa                                  = m_context.getRenderTarget().getNumSamples() > 1;
        const ProjectedBBox             projectedBBox                   = projectBoundingBox(config.bbox);
        const float                             lineWidth                               = (m_isWideLineCase) ? (m_wideLineLineWidth) : (1.0f);
        const tcu::IVec4                viewportBBoxArea                = getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
        const ProjectedBBox             projectedBBox                   = projectBoundingBox(config.bbox);
        const float                             lineWidth                               = (m_isWideLineCase) ? (m_wideLineLineWidth) : (1.0f);
        const tcu::IVec4                viewportBBoxArea                = getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
@@ -1795,6 +1802,7 @@ void LineRenderCase::verifyRenderResult (const IterationConfig& config)
 
        tcu::Surface                    viewportSurface                 (config.viewportSize.x(), config.viewportSize.y());
        bool                                    anyError                                = false;
 
        tcu::Surface                    viewportSurface                 (config.viewportSize.x(), config.viewportSize.y());
        bool                                    anyError                                = false;
+       bool                                    msaaRelaxationRequired  = false;
        int                                             messageLimitCounter             = 8;
 
        if (!m_calcPerPrimitiveBBox)
        int                                             messageLimitCounter             = 8;
 
        if (!m_calcPerPrimitiveBBox)
@@ -1828,23 +1836,53 @@ void LineRenderCase::verifyRenderResult (const IterationConfig& config)
 
        // scan rows
        for (int y = de::max(verificationArea.y(), viewportPatternArea.y()); y < de::min(verificationArea.w(), viewportPatternArea.w()); ++y)
 
        // scan rows
        for (int y = de::max(verificationArea.y(), viewportPatternArea.y()); y < de::min(verificationArea.w(), viewportPatternArea.w()); ++y)
-               anyError |= !scanRow(viewportSurface.getAccess(),
-                                                        y,
-                                                        verificationArea.x(),
-                                                        verificationArea.z(),
-                                                        expectedVerticalLines,
-                                                        messageLimitCounter);
+       {
+               const deUint8 result = !scanRow(viewportSurface.getAccess(),
+                                                                               y,
+                                                                               verificationArea.x(),
+                                                                               verificationArea.z(),
+                                                                               expectedVerticalLines,
+                                                                               messageLimitCounter);
+
+               if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
+                       anyError = true;
+               else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
+               {
+                       if (m_isWideLineCase && isMsaa)
+                       {
+                               // multisampled wide lines might not be supported
+                               msaaRelaxationRequired = true;
+                       }
+                       else
+                               anyError = true;
+               }
+       }
 
        // scan columns
        for (int x = de::max(verificationArea.x(), viewportPatternArea.x()); x < de::min(verificationArea.z(), viewportPatternArea.z()); ++x)
 
        // scan columns
        for (int x = de::max(verificationArea.x(), viewportPatternArea.x()); x < de::min(verificationArea.z(), viewportPatternArea.z()); ++x)
-               anyError |= !scanColumn(viewportSurface.getAccess(),
-                                                               x,
-                                                               verificationArea.y(),
-                                                               verificationArea.w(),
-                                                               expectedHorizontalLines,
-                                                               messageLimitCounter);
+       {
+               const deUint8 result = !scanColumn(viewportSurface.getAccess(),
+                                                                                  x,
+                                                                                  verificationArea.y(),
+                                                                                  verificationArea.w(),
+                                                                                  expectedHorizontalLines,
+                                                                                  messageLimitCounter);
 
 
-       if (anyError)
+               if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
+                       anyError = true;
+               else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
+               {
+                       if (m_isWideLineCase && isMsaa)
+                       {
+                               // multisampled wide lines might not be supported
+                               msaaRelaxationRequired = true;
+                       }
+                       else
+                               anyError = true;
+               }
+       }
+
+       if (anyError || msaaRelaxationRequired)
        {
                if (messageLimitCounter < 0)
                        m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
        {
                if (messageLimitCounter < 0)
                        m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
@@ -1857,7 +1895,13 @@ void LineRenderCase::verifyRenderResult (const IterationConfig& config)
                        << tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
                        << tcu::TestLog::EndImageSet;
 
                        << tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
                        << tcu::TestLog::EndImageSet;
 
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
+               if (anyError)
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
+               else
+               {
+                       // MSAA wide lines are optional
+                       m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Multisampled wide line verification failed");
+               }
        }
        else
        {
        }
        else
        {
@@ -1903,18 +1947,22 @@ tcu::IVec2 LineRenderCase::getNumberOfLinesRange (int queryAreaBegin, int queryA
        return tcu::IVec2(numLinesMin, numLinesMax);
 }
 
        return tcu::IVec2(numLinesMin, numLinesMax);
 }
 
-bool LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
+deUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
 {
        const bool numLinesOk   = checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
        const bool lineWidthOk  = checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
 {
        const bool numLinesOk   = checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
        const bool lineWidthOk  = checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
-       return numLinesOk && lineWidthOk;
+
+       return  (numLinesOk             ? (deUint8)SCANRESULT_NUM_LINES_OK_BIT  : 0u) |
+                       (lineWidthOk    ? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT : 0u);
 }
 
 }
 
-bool LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
+deUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
 {
        const bool numLinesOk   = checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
        const bool lineWidthOk  = checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
 {
        const bool numLinesOk   = checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
        const bool lineWidthOk  = checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
-       return numLinesOk && lineWidthOk;
+
+       return  (numLinesOk             ? (deUint8)SCANRESULT_NUM_LINES_OK_BIT  : 0u) |
+                       (lineWidthOk    ? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT : 0u);
 }
 
 bool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const
 }
 
 bool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const