Check KHR robust buffer access behavior
authorJames Helferty <jhelferty@nvidia.com>
Tue, 1 Aug 2017 16:42:33 +0000 (12:42 -0400)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Fri, 25 Aug 2017 11:56:37 +0000 (07:56 -0400)
Updates the storage buffer test for robust buffer access behavior to
verify against the narrower set of conditions imposed by the KHR
version of the extension. In the event that the KHR behavior is not
required, it will fall back to the old behavior.

VK-GL-CTS issue 499

Components: OpenGL

Affects:
* KHR-GLES32.robust.robust_buffer_access_behavior.storage_buffer
* KHR-GL43/44/45.robust_buffer_access_behavior.storage_buffer

Change-Id: I84d5cc10a99b58386c080eccd0e0801a02549477

external/openglcts/modules/common/glcRobustBufferAccessBehaviorTests.cpp
external/openglcts/modules/common/glcRobustBufferAccessBehaviorTests.hpp

index ab719d3..d721e91 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "glcRobustBufferAccessBehaviorTests.hpp"
 
+#include "gluContextInfo.hpp"
 #include "gluDefs.hpp"
 #include "glwEnums.hpp"
 #include "glwFunctions.hpp"
@@ -3280,6 +3281,10 @@ bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
        return result;
 }
 
+/* StorageBufferTest constants */
+const GLfloat StorageBufferTest::m_destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+const GLfloat StorageBufferTest::m_source_data[4]              = { 2.0f, 3.0f, 4.0f, 5.0f };
+
 /** Constructor
  *
  * @param context Test context
@@ -3287,6 +3292,7 @@ bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
 StorageBufferTest::StorageBufferTest(deqp::Context& context)
        : TestCase(context, "storage_buffer", "Verifies that out-of-bound access to SSBO is discared or resutls in 0")
        , m_test_case(VALID)
+       , m_hasKhrRobustBufferAccess(false)
 {
        /* Nothing to be done here */
 }
@@ -3307,12 +3313,13 @@ StorageBufferTest::StorageBufferTest(deqp::Context& context, const glw::GLchar*
  **/
 tcu::TestNode::IterateResult StorageBufferTest::iterate()
 {
-       static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
-       static const GLfloat source_data[4]              = { 2.0f, 3.0f, 4.0f, 5.0f };
 
        /* GL entry points */
        const Functions& gl = m_context.getRenderContext().getFunctions();
 
+       m_hasKhrRobustBufferAccess = m_context.getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior") ||
+                                                                contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5));
+
        /* Test result indicator */
        bool test_result = true;
 
@@ -3328,9 +3335,9 @@ tcu::TestNode::IterateResult StorageBufferTest::iterate()
                const std::string& cs = getComputeShader();
 
                /* Buffers initialization */
-               destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
-                                                                       destination_data);
-               source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
+               destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_destination_data),
+                                                                       m_destination_data);
+               source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_source_data), m_source_data);
 
                destination_buffer.BindBase(0);
                source_buffer.BindBase(1);
@@ -3350,7 +3357,7 @@ tcu::TestNode::IterateResult StorageBufferTest::iterate()
                /* Verify results */
                destination_buffer.Bind();
                GLfloat* buffer_data =
-                       (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
+                       (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(m_destination_data), GL_MAP_READ_BIT);
                GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
 
                test_result = verifyResults(buffer_data);
@@ -3440,39 +3447,119 @@ std::string StorageBufferTest::getComputeShader()
  **/
 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
 {
-       static const GLfloat expected_data_valid[4]                               = { 2.0f, 3.0f, 4.0f, 5.0f };
-       static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
-       static const GLfloat expected_data_invalid_source[4]      = { 0.0f, 0.0f, 0.0f, 0.0f };
-
-       int size = static_cast<int>(sizeof(GLfloat) * 4);
+       /* KHR_robust_buffer_access_behavior (and also GL 4.5 and later) states
+        * which values can be expected when reading or writing outside of a
+        * buffer's range. If supported, we will compare results against those
+        * expectations.
+        *
+        * Otherwise, we will attempt to match results against previously observed
+        * and valid behavior.
+        */
+       static const GLfloat expected_data_valid[4]                                = { 2.0f, 3.0f, 4.0f, 5.0f };
+       static const GLfloat expected_data_invalid_source[4]       = { 0.0f, 0.0f, 0.0f, 0.0f };
+       static const GLfloat expected_data_invalid_destination[4]  = { 1.0f, 1.0f, 1.0f, 1.0f };
 
        /* Prepare expected data const for proper case*/
-       const GLfloat* expected_data = 0;
-       const GLchar*  name                      = 0;
+       const GLchar*  name                                = 0;
+       bool               check_expected_data = false;
+       const GLfloat* expected_data       = 0;
        switch (m_test_case)
        {
        case VALID:
-               expected_data = expected_data_valid;
-               name              = "valid indices";
+               name                            = "valid indices";
+               check_expected_data     = true;
+               expected_data           = expected_data_valid;
                break;
        case SOURCE_INVALID:
-               expected_data = expected_data_invalid_source;
-               name              = "invalid source indices";
+               name                            = "invalid source indices";
+               if (m_hasKhrRobustBufferAccess)
+               {
+                       for (int b = 0; b < 4; b++)
+                       {
+                               /* Each out-of-range read can either be 0 or any value within
+                                * the source buffer.
+                                * */
+                               bool valid = false;
+                               if (buffer_data[b] == 0.0f)
+                               {
+                                       valid = true;
+                               }
+                               else
+                               {
+                                       for (int c = 0; c < 4 && !valid; c++)
+                                       {
+                                               if (buffer_data[b] == m_source_data[c])
+                                               {
+                                                       valid = true;
+                                               }
+                                       }
+                               }
+                               if (!valid)
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
+                                                                                                               << tcu::TestLog::EndMessage;
+                               }
+                       }
+               }
+               else
+               {
+                       check_expected_data     = true;
+                       expected_data           = expected_data_invalid_source;
+               }
                break;
        case DESTINATION_INVALID:
-               expected_data = expected_data_invalid_destination;
-               name              = "invalid destination indices";
+               name                            = "invalid destination indices";
+               if (m_hasKhrRobustBufferAccess)
+               {
+                       for (int b = 0; b < 4; b++)
+                       {
+                               bool valid = false;
+                               /* Each out-of-range write can either be discarded (in which
+                                * case it would have the original destination value) or it
+                                * could write any value within the buffer (so we need to check
+                                * against each possible source value).
+                                */
+                               if (buffer_data[b] == m_destination_data[b])
+                               {
+                                       valid = true;
+                               }
+                               else
+                               {
+                                       for (int c = 0; c < 4 && !valid; c++)
+                                       {
+                                               if (buffer_data[b] == m_source_data[c])
+                                               {
+                                                       valid = true;
+                                               }
+                                       }
+                               }
+                               if (!valid)
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
+                                                                                                               << tcu::TestLog::EndMessage;
+                               }
+                       }
+               }
+               else
+               {
+                       check_expected_data     = true;
+                       expected_data           = expected_data_invalid_destination;
+               }
                break;
        default:
                TCU_FAIL("Invalid enum");
        }
 
-       /* Verify buffer data */
-       if (0 != memcmp(expected_data, buffer_data, size))
+       if (check_expected_data)
        {
-               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
-                                                                                       << tcu::TestLog::EndMessage;
-               return false;
+               /* Verify buffer data */
+               int size = static_cast<int>(sizeof(GLfloat) * 4);
+               if (0 != memcmp(expected_data, buffer_data, size))
+               {
+                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
+                                                                                               << tcu::TestLog::EndMessage;
+                       return false;
+               }
        }
 
        return true;
index e7dd677..411183b 100644 (file)
@@ -513,6 +513,11 @@ protected:
 
        /* Protected fields */
        VERSION m_test_case;
+       bool m_hasKhrRobustBufferAccess;
+
+       /* Protected constants */
+       static const glw::GLfloat m_destination_data[4];
+       static const glw::GLfloat m_source_data[4];
 };
 
 /** Implementation of test UniformBuffer. Description follows: