Add SSBO block tests
authorMichael Hadley <michael.hadley@mobica.com>
Thu, 1 Dec 2016 17:52:17 +0000 (17:52 +0000)
committerPyry Haulos <phaulos@google.com>
Mon, 30 Jan 2017 22:33:02 +0000 (14:33 -0800)
New Tests:
- dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_block.*

Change-Id: I60d52bc34d9211e93332dcc719535f1f5e4a0596

Android.mk
android/cts/master/gles31-master.txt
modules/gles31/functional/CMakeLists.txt
modules/gles31/functional/es31fDebugTests.cpp
modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp [new file with mode: 0644]
modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp [new file with mode: 0644]

index fa93f8b..a947dc2 100644 (file)
@@ -591,6 +591,7 @@ LOCAL_SRC_FILES := \
        modules/gles31/functional/es31fNegativeShaderImageLoadStoreTests.cpp \
        modules/gles31/functional/es31fNegativeShaderStorageTests.cpp \
        modules/gles31/functional/es31fNegativeStateApiTests.cpp \
+       modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp \
        modules/gles31/functional/es31fNegativeTessellationTests.cpp \
        modules/gles31/functional/es31fNegativeTestShared.cpp \
        modules/gles31/functional/es31fNegativeTextureApiTests.cpp \
index 1e716dc..939f1e4 100644 (file)
@@ -16769,6 +16769,8 @@ dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.shader
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_argument
@@ -17224,6 +17226,8 @@ dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.shader_io_bl
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_argument
@@ -17677,6 +17681,8 @@ dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.shader
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_argument
index 4cf4687..8c6edea 100644 (file)
@@ -177,6 +177,8 @@ set(DEQP_GLES31_FUNCTIONAL_SRCS
        es31fDrawBuffersIndexedTests.cpp
        es31fNegativeShaderStorageTests.cpp
        es31fNegativeShaderStorageTests.hpp
+       es31fNegativeSSBOBlockTests.cpp
+       es31fNegativeSSBOBlockTests.hpp
        )
 
 add_library(deqp-gles31-functional STATIC ${DEQP_GLES31_FUNCTIONAL_SRCS})
index 5fd3b68..d41addb 100644 (file)
@@ -34,6 +34,7 @@
 #include "es31fNegativeShaderImageLoadStoreTests.hpp"
 #include "es31fNegativeShaderFunctionTests.hpp"
 #include "es31fNegativeShaderDirectiveTests.hpp"
+#include "es31fNegativeSSBOBlockTests.hpp"
 #include "es31fNegativePreciseTests.hpp"
 #include "es31fNegativeAdvancedBlendEquationTests.hpp"
 #include "es31fNegativeShaderStorageTests.hpp"
@@ -2955,6 +2956,7 @@ void DebugTests::init (void)
        const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions());
        const vector<FunctionContainer> shaderFunctionFuncs              = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
        const vector<FunctionContainer> shaderDirectiveFuncs     = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
+       const vector<FunctionContainer> ssboBlockFuncs                   = wrapCoreFunctions(NegativeTestShared::getNegativeSSBOBlockTestFunctions());
        const vector<FunctionContainer> preciseFuncs                     = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
        const vector<FunctionContainer> advancedBlendFuncs               = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
        const vector<FunctionContainer> shaderStorageFuncs               = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
@@ -3061,6 +3063,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange",          "Negative Shader Image Atomic Exchange API Cases",      imageAtomicExchangeFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function",                        "Negative Shader Function Cases",                                       shaderFunctionFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive",                       "Negative Shader Directive Cases",                                      shaderDirectiveFuncs));
+                       host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "ssbo_block",                                     "Negative SSBO Block Cases",                                            ssboBlockFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise",                                        "Negative Precise Cases",                                                       preciseFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend",                         "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage",                         "Negative Shader Storage Cases",                                        shaderStorageFuncs));
@@ -3085,6 +3088,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange",       "Negative Shader Image Atomic Exchange API Cases",      imageAtomicExchangeFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function",                     "Negative Shader Function Cases",                                       shaderFunctionFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive",            "Negative Shader Directive Cases",                                      shaderDirectiveFuncs));
+                       host->addChild(createChildCases(CASETYPE_LOG, m_context, "ssbo_block",                          "Negative SSBO Block Cases",                                            ssboBlockFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise",                                     "Negative Precise Cases",                                                       preciseFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend",                      "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage",                      "Negative Shader Storage Cases",                                        shaderStorageFuncs));
@@ -3109,6 +3113,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange",          "Negative Shader Image Atomic Exchange API Cases",      imageAtomicExchangeFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function",                        "Negative Shader Function Cases",                                       shaderFunctionFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive",                       "Negative Shader Directive Cases",                                      shaderDirectiveFuncs));
+                       host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "ssbo_block",                                     "Negative SSBO Block Cases",                                            ssboBlockFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise",                                        "Negative Precise Cases",                                                       preciseFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend",                         "Negative Advanced Blend Equation Cases",                       advancedBlendFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage",                         "Negative Shader Storage Cases",                                        shaderStorageFuncs));
diff --git a/modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp b/modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp
new file mode 100644 (file)
index 0000000..bddd035
--- /dev/null
@@ -0,0 +1,617 @@
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*!
+* \file
+* \brief Negative Shader Storage Buffer Object (SSBO) tests.
+*//*--------------------------------------------------------------------*/
+#include "es31fNegativeSSBOBlockTests.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+#include "gluShaderProgram.hpp"
+#include <map>
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+using tcu::TestLog;
+using glu::CallLogWrapper;
+using namespace glw;
+namespace args
+{
+enum ArgMember
+{
+       ARGMEMBER_FORMAT                        =       0,
+       ARGMEMBER_BINDING_POINT,
+       ARGMEMBER_MATRIX_ORDER,
+       ARGMEMBER_MEMBER_TYPE,
+       ARGMEMBER_NAME,
+       ARGMEMBER_FIXED_ARRAY,
+       ARGMEMBER_VARIABLE_ARRAY,
+       ARGMEMBER_REORDER
+};
+
+// key pair ssbo arg data
+struct SsboArgData
+{
+       ArgMember       member;
+       std::string     data;
+
+       SsboArgData(const ArgMember& member_, const std::string& data_)
+       {
+               member  =       member_;
+               data    =       data_;
+       }
+};
+
+// class which manages string based argument used to build varying ssbo interface blocks and members
+class SsboArgs
+{
+public:
+                                       SsboArgs(const std::string version, tcu::TestLog& log);
+
+       void                    setSingleValue                                          (const SsboArgData argData);
+       bool                    setAllValues                                            (const std::vector<SsboArgData> argDataList);
+
+       const std::string&      getContextVersion                               (void) const;
+       const std::string&      getStdFormat                                    (void) const;
+       const std::string&      getBindingPoint                                 (void) const;
+       const std::string&      getMatrixOrder                                  (void) const;
+       const std::string&      getMemberType                                   (void) const;
+       const std::string&      getMemberName                                   (void) const;
+       const std::string&      getMemberFixedArrayName                 (void) const;
+       const std::string&      getMemberVariableArray                  (void) const;
+       bool                            getMemberReorder                                (void) const;
+       int                                     getNumberMembers                                (void) const;
+
+       void                            resetValues                                             (void);
+
+       std::map<std::string, std::string>      populateArgsMap (void) const;
+
+private:
+       std::string             m_negativeContextVersion;
+       std::string             m_stdFormat;
+       std::string             m_bindingPoint;
+       std::string             m_matrixOrder;
+       std::string             m_memberType;
+       std::string             m_memberName;
+       std::string             m_memberFixedArrayerName;
+       std::string             m_memberVariableArray;
+       bool                    m_memberReorder;
+       int                             m_numberMembers;
+       tcu::TestLog&   m_testLog;
+
+       void                    setDefaultValues                                        (void);
+};
+
+//constructor which ensure a proper context is passed into the struct
+SsboArgs::SsboArgs(const std::string version, tcu::TestLog& log)
+       : m_negativeContextVersion      (version)
+       , m_numberMembers                       (8)
+       , m_testLog                                     (log)
+{
+       setDefaultValues();
+}
+
+void SsboArgs::setSingleValue (const SsboArgData argData)
+{
+       std::string message;
+
+       switch (argData.member)
+       {
+               case ARGMEMBER_FORMAT:
+                       m_stdFormat                                     =       argData.data;
+                       return;
+               case ARGMEMBER_BINDING_POINT:
+                       m_bindingPoint                          =       argData.data;
+                       return;
+               case ARGMEMBER_MATRIX_ORDER:
+                       m_matrixOrder                           =       argData.data;
+                       return;
+               case ARGMEMBER_MEMBER_TYPE:
+                       m_memberType                            =       argData.data;
+                       return;
+               case ARGMEMBER_NAME:
+                       m_memberName                            =       argData.data;
+                       return;
+               case ARGMEMBER_FIXED_ARRAY:
+                       m_memberFixedArrayerName        =       argData.data;
+                       return;
+               case ARGMEMBER_VARIABLE_ARRAY:
+                       m_memberVariableArray           =       argData.data;
+                       return;
+               case ARGMEMBER_REORDER:
+                       if (argData.data == "true")
+                       {
+                               m_memberReorder                 =       true;
+                       }
+                       return;
+               default:
+                       message = "auto loop argument data member not recognised.";
+                       m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+       }
+}
+
+bool SsboArgs::setAllValues (const std::vector<SsboArgData> argDataList)
+{
+       std::string     message;
+
+       if ((argDataList.size() == 0) || (argDataList.size() > (size_t)m_numberMembers))
+       {
+               message = "set of args does not match the number of args struct changeable members.";
+               m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+               return false;
+       }
+       else
+       {
+               for (unsigned int idx = 0; idx < argDataList.size(); idx++)
+               {
+                       setSingleValue(argDataList[idx]);
+               }
+       }
+
+       return true;
+}
+
+const std::string& SsboArgs::getContextVersion (void) const
+{
+       return m_negativeContextVersion;
+}
+
+const std::string& SsboArgs::getStdFormat (void) const
+{
+       return m_stdFormat;
+}
+
+const std::string& SsboArgs::getBindingPoint (void) const
+{
+       return m_bindingPoint;
+}
+
+const std::string& SsboArgs::getMatrixOrder (void) const
+{
+       return m_matrixOrder;
+}
+
+const std::string& SsboArgs::getMemberType (void) const
+{
+       return m_memberType;
+}
+
+const std::string& SsboArgs::getMemberName (void) const
+{
+       return m_memberName;
+}
+
+const std::string& SsboArgs::getMemberFixedArrayName (void) const
+{
+       return m_memberFixedArrayerName;
+}
+
+const std::string& SsboArgs::getMemberVariableArray (void) const
+{
+       return m_memberVariableArray;
+}
+
+bool SsboArgs::getMemberReorder (void) const
+{
+       return m_memberReorder;
+}
+
+int SsboArgs::getNumberMembers (void) const
+{
+       return m_numberMembers;
+}
+
+void SsboArgs::resetValues (void)
+{
+       setDefaultValues();
+}
+
+//converts SsboArgs member variable into a map object to be used by tcu::StringTemplate
+std::map<std::string, std::string> SsboArgs::populateArgsMap (void) const
+{
+       std::map<std::string, std::string> argsMap;
+
+       // key placeholders located at specific points in the ssbo block
+       argsMap["NEGATIVE_CONTEXT_VERSION"]     =       m_negativeContextVersion;
+       argsMap["STD_FORMAT"]                           =       m_stdFormat;
+       argsMap["BINDING_POINT"]                        =       m_bindingPoint;
+       argsMap["MATRIX_ORDER"]                         =       m_matrixOrder;
+       argsMap["MEMBER_TYPE"]                          =       m_memberType;
+       argsMap["MEMBER_NAME"]                          =       m_memberName;
+       argsMap["MEMBER_FIXED_ARRAY"]           =       m_memberFixedArrayerName;
+       argsMap["MEMBER_VARIABLE_ARRAY"]        =       m_memberVariableArray;
+
+       return argsMap;
+}
+
+// default values i.e. same shader template
+void SsboArgs::setDefaultValues (void)
+{
+       m_stdFormat                                     =       "std430";
+       m_bindingPoint                          =       "0";
+       m_matrixOrder                           =       "column_major";
+       m_memberType                            =       "int";
+       m_memberName                            =       "matrix";
+       m_memberFixedArrayerName        =       "10";
+       m_memberVariableArray           =       "";
+       m_memberReorder                         =       false;
+}
+} // args
+
+std::string generateVaryingSSBOShader(const glw::GLenum shaderType, const args::SsboArgs& args, tcu::TestLog& log)
+{
+       std::map<std::string, std::string>      argsMap;
+       std::ostringstream                                      source;
+       std::string                                                     sourceString;
+       std::stringstream                                       ssboString;
+       std::string                                                     message;
+
+       if (args.getMemberReorder())
+       {
+               ssboString      << "    mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+                                       << "    highp mat4 ${MEMBER_NAME};\n"
+                                       << "    lowp ${MEMBER_TYPE} data;\n"
+                                       << "    mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+       }
+       else
+       {
+               ssboString      << "    lowp ${MEMBER_TYPE} data;\n"
+                                       << "    highp mat4 ${MEMBER_NAME};\n"
+                                       << "    mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+                                       << "    mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+       }
+
+       argsMap = args.populateArgsMap();
+
+       switch (shaderType)
+       {
+               case GL_VERTEX_SHADER:
+               {
+                       source  << "${NEGATIVE_CONTEXT_VERSION}\n"
+                                       << "layout (location = 0) in highp vec4 position;\n"
+                                       << "layout (location = 1) in mediump vec4 colour;\n"
+                                       << "out mediump vec4 vertex_colour;\n"
+                                       << "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+                                       << "{\n";
+
+                       source << ssboString.str();
+
+                       source  << "} ssbo;\n"
+                                       << "void main()\n"
+                                       << "{\n"
+                                       << "    mediump vec4 variable;\n"
+                                       << "    gl_Position = ssbo.${MEMBER_NAME} * position;\n"
+                                       << "    for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+                                       << "    {\n"
+                                       << "            variable += ssbo.array_1[idx];\n"
+                                       << "    }\n"
+                                       << "    vertex_colour = colour + variable;\n"
+                                       << "}\n";
+
+                       sourceString = source.str();
+                       sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+                       return sourceString;
+               }
+
+               case GL_FRAGMENT_SHADER:
+               {
+                       source  << "${NEGATIVE_CONTEXT_VERSION}\n"
+                                       << "in mediump vec4 vertex_colour;\n"
+                                       << "layout (location = 0) out mediump vec4 fragment_colour;\n"
+                                       << "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+                                       << "{\n";
+
+                       source << ssboString.str();
+
+                       source  << "} ssbo;\n"
+                                       << "void main()\n"
+                                       << "{\n"
+                                       << "    mediump vec4 variable;\n"
+                                       << "    variable * ssbo.${MEMBER_NAME};\n"
+                                       << "    for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+                                       << "    {\n"
+                                       << "            variable += ssbo.array_1[idx];\n"
+                                       << "    }\n"
+                                       << "    fragment_colour = vertex_colour + variable;\n"
+                                       << "}\n";
+
+                       sourceString = source.str();
+                       sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+                       return sourceString;
+               }
+
+               case GL_GEOMETRY_SHADER:
+               {
+                       // TODO:
+                       return sourceString;
+               }
+
+               case GL_TESS_CONTROL_SHADER:
+               {
+                       // TODO:
+                       return sourceString;
+               }
+
+               case GL_TESS_EVALUATION_SHADER:
+               {
+                       // TODO:
+                       return sourceString;
+               }
+
+               case GL_COMPUTE_SHADER:
+               {
+                       // TODO:
+                       return sourceString;
+               }
+
+               default:
+               {
+                       message = "shader type not recognised.";
+                       log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               }
+       }
+
+       return std::string();
+}
+
+void logProgramInfo(NegativeTestContext& ctx, GLint program)
+{
+       GLint                   maxLength       =       0;
+       std::string             message;
+       tcu::TestLog&   log                     =       ctx.getLog();
+
+       ctx.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+
+       message = "Program log:";
+       log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+       if (maxLength == 0)
+       {
+               message = "No available info log.";
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               return;
+       }
+
+       std::vector<GLchar> infoLog(maxLength);
+       ctx.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
+
+       std::string programLogMessage(&infoLog[0], maxLength);
+       log << tcu::TestLog::Message << programLogMessage << tcu::TestLog::EndMessage;
+}
+
+void ssbo_block_matching(NegativeTestContext& ctx)
+{
+       const bool                              isES32                                                                                                  =       contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       const glu::GLSLVersion  version                                                                                                 =       isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+       tcu::TestLog&                   log                                                                                                             =       ctx.getLog();
+       std::string                             message;
+       std::string                             versionString(glu::getGLSLVersionDeclaration(version));
+       args::SsboArgs                  ssboArgs(versionString, log);
+       GLint                                   shaderVertexGL;
+       std::string                             shaderVertexString;
+       const char*                             shaderVertexCharPtr;
+
+       // List of arguments used to create varying ssbo objects in the fragment shader
+       const args::SsboArgData argDataArrayFrag[] = {  args::SsboArgData(args::ARGMEMBER_FORMAT,                       "std140"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_BINDING_POINT,        "10"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,         "row_major"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_MEMBER_TYPE,          "vec2"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_NAME,                         "name_changed"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,          "20"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,       "5"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_REORDER,                      "true") };
+       std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+       // create default vertex shader
+       shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+       shaderVertexCharPtr = shaderVertexString.c_str();
+       shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+       // log
+       message = shaderVertexString;
+       log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+       // compile
+       ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+       ctx.glCompileShader(shaderVertexGL);
+
+       for (std::size_t idx = 0; idx < argDataVectorFrag.size(); ++idx)
+       {
+               GLint                   linkStatus                              =       -1;
+               GLint                   program;
+               GLint                   shaderFragmentGL;
+               std::string             shaderFragmentString;
+               const char*             shaderFragmentCharPtr;
+
+               ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+               program = ctx.glCreateProgram();
+
+               // reset args to default and make a single change
+               ssboArgs.resetValues();
+               ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+               // create fragment shader
+               shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+               shaderFragmentCharPtr = shaderFragmentString.c_str();
+               shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+               // log
+               message = shaderFragmentString;
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+               // compile
+               ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+               ctx.glCompileShader(shaderFragmentGL);
+
+               // attach shaders to program and attempt to link
+               ctx.glAttachShader(program, shaderVertexGL);
+               ctx.glAttachShader(program, shaderFragmentGL);
+               ctx.glLinkProgram(program);
+               ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+               logProgramInfo(ctx, program);
+
+               if (linkStatus == GL_TRUE)
+               {
+                       ctx.fail("Program should not have linked");
+               }
+
+               // clean up resources
+               ctx.glDeleteShader(shaderFragmentGL);
+               ctx.glDeleteProgram(program);
+
+               ctx.endSection();
+       }
+
+       // clean up default resources
+       ctx.glDeleteShader(shaderVertexGL);
+}
+
+void ssbo_block_shared_qualifier(NegativeTestContext& ctx)
+{
+       const bool                              isES32                                                                                                  =       contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       const glu::GLSLVersion  version                                                                                                 =       isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+       tcu::TestLog&                   log                                                                                                             =       ctx.getLog();
+       std::string                             message;
+       std::string                             versionString(glu::getGLSLVersionDeclaration(version));
+       args::SsboArgs                  ssboArgs(versionString, log);
+       bool                                    result;
+       GLint                                   shaderVertexGL;
+       std::string                             shaderVertexString;
+       const char*                             shaderVertexCharPtr;
+
+       // default args used in vertex shader ssbo
+       const args::SsboArgData argDataArrayVert[] = {  args::SsboArgData(args::ARGMEMBER_FORMAT,                       "shared"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_BINDING_POINT,        "0"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,         "column_major"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,          "10"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,       "10"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_REORDER,                      "false") };
+       std::vector<args::SsboArgData> argDataVectorVert(argDataArrayVert, argDataArrayVert + sizeof(argDataArrayVert) / sizeof(argDataArrayVert[0]));
+
+       // args changed in fragment shader ssbo
+       const args::SsboArgData argDataArrayFrag[] = {  args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,         "row_major"),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,       ""),
+                                                                                                       args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,          "20") };
+       std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+       // set default vertex ssbo args
+       result = ssboArgs.setAllValues(argDataVectorVert);
+
+       if (result == false)
+       {
+               message = "Invalid use of args.setAllValues()";
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               return;
+       }
+
+       // create default vertex shader
+       shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+       shaderVertexCharPtr = shaderVertexString.c_str();
+       shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+       // log
+       message = shaderVertexString;
+       log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+       // compile
+       ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+       ctx.glCompileShader(shaderVertexGL);
+
+       for (std::size_t idx = 0; idx < argDataVectorFrag.size(); idx++)
+       {
+               GLint           linkStatus                              =       -1;
+               GLint           program;
+               GLint           shaderFragmentGL;
+               std::string     shaderFragmentString;
+               const char*     shaderFragmentCharPtr;
+
+               ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+               program = ctx.glCreateProgram();
+
+               // reset args to default and make a single change
+               ssboArgs.setAllValues(argDataVectorVert);
+               ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+               // create fragment shader
+               shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+               shaderFragmentCharPtr = shaderFragmentString.c_str();
+               shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+               // log
+               message = shaderFragmentString;
+               log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+               // compile
+               ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+               ctx.glCompileShader(shaderFragmentGL);
+
+               // attach shaders to the program and attempt to link
+               ctx.glAttachShader(program, shaderVertexGL);
+               ctx.glAttachShader(program, shaderFragmentGL);
+               ctx.glLinkProgram(program);
+               ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+               logProgramInfo(ctx, program);
+
+               if (linkStatus == GL_TRUE)
+               {
+                       ctx.fail("Program should not have linked");
+               }
+
+               // clean up resources
+               ctx.glDeleteShader(shaderFragmentGL);
+               ctx.glDeleteProgram(program);
+
+               ctx.endSection();
+       }
+
+       // clean up default resources
+       ctx.glDeleteShader(shaderVertexGL);
+}
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void)
+{
+       const FunctionContainer funcs[] =
+       {
+               { ssbo_block_matching,                  "ssbo_block_interface_matching_tests",  "Invalid Shader Linkage" },
+               { ssbo_block_shared_qualifier,  "ssbo_using_shared_qualifier_tests",    "Invalid Shader Linkage" },
+       };
+
+       return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+} // NegativeTestShared
+} //Functional
+} //gles31
+} //deqp
diff --git a/modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp b/modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp
new file mode 100644 (file)
index 0000000..db1d3bb
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+#define _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*!
+* \file
+* \brief Negative Shader Storage Block Object (SSBO) API tests.
+*//*--------------------------------------------------------------------*/
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FNEGATIVESSBOBLOCKTESTS_HPP
\ No newline at end of file