Import dEQP fixes from an internal repo.
authorJarkko Pöyry <jpoyry@google.com>
Wed, 15 Oct 2014 20:34:56 +0000 (13:34 -0700)
committerJarkko Pöyry <jpoyry@google.com>
Wed, 15 Oct 2014 20:34:56 +0000 (13:34 -0700)
 * Update XFB program interface tests to match spec update in Khronos
   bug 12787.
 * Add tests for whole array and built-in XFB PIQ.
 * Convert incorrect linkage.varying.rules.interpolation_mismatch_
   negative cases to positive cases.

Change-Id: Ic5eab213f6ee7a5151220664107c6f912fd12130

data/gles3/shaders/linkage.test
modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp
modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp
modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp

index 3c6a7bf..89d4180 100644 (file)
@@ -464,54 +464,68 @@ group varying "Varying linkage"
                        ""
                end
 
-               # mismatched interpolation
-               case interpolation_mismatch_1
+               # different interpolation
+               case differing_interpolation_1
                        version 300 es
-                       desc "varying interpolation mismatch (flat vs. smooth)"
-                       expect link_fail
+                       desc "varying interpolation different (flat vs. smooth)"
+                       values
+                       {
+                               input float in0         = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+                               output float out0       = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+                       }
+
                        vertex ""
                                #version 300 es
                                ${VERTEX_DECLARATIONS}
                                flat out mediump float var;
                                void main()
                                {
-                                       var = 2.0;
+                                       var = in0;
                                        ${VERTEX_OUTPUT}
                                }
                        ""
                        fragment ""
                                #version 300 es
+                               precision mediump float;
                                ${FRAGMENT_DECLARATIONS}
                                in mediump float var;
                                void main()
                                {
-                                       ${FRAG_COLOR} = vec4(var);
+                                       out0 = var;
+                                       ${FRAGMENT_OUTPUT}
                                }
                        ""
                end
 
-               # mismatched interpolation
-               case interpolation_mismatch_2
+               # different interpolation
+               case differing_interpolation_2
                        version 300 es
-                       desc "varying interpolation mismatch (smooth vs. centroid)"
-                       expect link_fail
+                       desc "varying interpolation different (smooth vs. centroid)"
+                       values
+                       {
+                               input float in0         = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+                               output float out0       = [ -1.25 | -25.0 | 1.0 | 2.25 | 3.4 | 16.0 ];
+                       }
+
                        vertex ""
                                #version 300 es
                                ${VERTEX_DECLARATIONS}
                                smooth out mediump float var;
                                void main()
                                {
-                                       var = 2.0;
+                                       var = in0;
                                        ${VERTEX_OUTPUT}
                                }
                        ""
                        fragment ""
                                #version 300 es
+                               precision mediump float;
                                ${FRAGMENT_DECLARATIONS}
                                centroid in mediump float var;
                                void main()
                                {
-                                       ${FRAG_COLOR} = vec4(var);
+                                       out0 = var;
+                                       ${FRAGMENT_OUTPUT}
                                }
                        ""
                end
index a9d32ca..ccc0d80 100644 (file)
@@ -72,25 +72,41 @@ static bool incrementMultiDimensionIndex (std::vector<int>& index, const std::ve
        return (incrementDimensionNdx != -1);
 }
 
-void generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, bool isTopLevelBufferVariable)
+void generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags)
 {
+       DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0);
+
+       // remove top-level flag from children
+       const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE);
+
        if (type.isBasicType())
                resources.push_back(name);
        else if (type.isStructType())
        {
                const glu::StructType* structType = type.getStructPtr();
                for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx)
-                       generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), false);
+                       generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags);
        }
        else if (type.isArrayType())
        {
+               // Bottom-level arrays of basic types of a transform feedback variable will produce only the first
+               // element but without the trailing "[0]"
+               if (type.getElementType().isBasicType() &&
+                       (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0)
+               {
+                       resources.push_back(name);
+               }
                // Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element
-               if (type.getElementType().isBasicType() || isTopLevelBufferVariable)
-                       generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), false);
+               else if (type.getElementType().isBasicType() ||
+                                (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0)
+               {
+                       generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags);
+               }
+               // Other arrays of aggregate types are expanded
                else
                {
                        for (int ndx = 0; ndx < type.getArraySize(); ++ndx)
-                               generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), false);
+                               generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags);
                }
        }
        else
@@ -370,9 +386,9 @@ static void writeInterfaceWriteExpression (std::ostringstream& buf, const std::s
        }
 }
 
-static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* pathWithoutName, const glu::VarType& type)
+static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type)
 {
-       glu::VarTokenizer tokenizer(pathWithoutName);
+       glu::VarTokenizer tokenizer(subPath);
 
        typePath.push_back(VariablePathComponent(&type));
 
@@ -389,7 +405,7 @@ static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath,
 
                for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
                        if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier())
-                               return traverseVariablePath(typePath, pathWithoutName + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());
+                               return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());
 
                // malformed path, no such member
                return false;
@@ -406,7 +422,7 @@ static bool traverseVariablePath (std::vector<VariablePathComponent>& typePath,
                if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET)
                        return false;
 
-               return traverseVariablePath(typePath, pathWithoutName + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
+               return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
        }
 
        return false;
@@ -886,7 +902,12 @@ std::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::
        std::vector<std::string>        resources;
 
        for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx)
-               generateVariableTypeResourceNames(resources, namePrefix + interfaceBlock.variables[variableNdx].name, interfaceBlock.variables[variableNdx].varType, isTopLevelBufferVariable);
+               generateVariableTypeResourceNames(resources,
+                                                                                 namePrefix + interfaceBlock.variables[variableNdx].name,
+                                                                                 interfaceBlock.variables[variableNdx].varType,
+                                                                                 (isTopLevelBufferVariable) ?
+                                                                                       (RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) :
+                                                                                       (RESOURCE_NAME_GENERATION_FLAG_DEFAULT));
 
        return resources;
 }
@@ -913,7 +934,10 @@ std::vector<std::string> getProgramInterfaceResourceList (const ProgramInterface
 
                                for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
                                        if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
-                                               generateVariableTypeResourceNames(resources, shader->getDefaultBlock().variables[variableNdx].name, shader->getDefaultBlock().variables[variableNdx].varType, false);
+                                               generateVariableTypeResourceNames(resources,
+                                                                                                                 shader->getDefaultBlock().variables[variableNdx].name,
+                                                                                                                 shader->getDefaultBlock().variables[variableNdx].varType,
+                                                                                                                 RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
 
                                for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
                                {
@@ -981,7 +1005,10 @@ std::vector<std::string> getProgramInterfaceResourceList (const ProgramInterface
 
                                for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
                                        if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
-                                               generateVariableTypeResourceNames(resources, shader->getDefaultBlock().variables[variableNdx].name, shader->getDefaultBlock().variables[variableNdx].varType, false);
+                                               generateVariableTypeResourceNames(resources,
+                                                                                                                 shader->getDefaultBlock().variables[variableNdx].name,
+                                                                                                                 shader->getDefaultBlock().variables[variableNdx].varType,
+                                                                                                                 RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
 
                                for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
                                {
@@ -1037,15 +1064,22 @@ std::vector<std::string> getProgramInterfaceResourceList (const ProgramInterface
                {
                        for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
                        {
-                               const std::string                                       varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
-                               std::vector<VariablePathComponent>      path;
+                               const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
 
                                if (deStringBeginsWith(varyingName.c_str(), "gl_"))
                                        resources.push_back(varyingName); // builtin
-                               else if (traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
-                                       generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(), false);
                                else
-                                       DE_ASSERT(false); // Program failed validate, invalid operation
+                               {
+                                       std::vector<VariablePathComponent> path;
+
+                                       if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
+                                               DE_ASSERT(false); // Program failed validate, invalid operation
+
+                                       generateVariableTypeResourceNames(resources,
+                                                                                                         varyingName,
+                                                                                                         *path.back().getVariableType(),
+                                                                                                         RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
+                               }
                        }
 
                        break;
index 9e6cea1..0117013 100644 (file)
@@ -151,11 +151,20 @@ struct ProgramResourceUsage
 
 } // ProgramInterfaceDefinition
 
+enum ResourceNameGenerationFlag
+{
+       RESOURCE_NAME_GENERATION_FLAG_DEFAULT                                           = 0x0,
+       RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE         = 0x1,
+       RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE       = 0x2,
+
+       RESOURCE_NAME_GENERATION_FLAG_MASK                                                      = 0x3
+};
+
 std::vector<std::string>                                                       getProgramInterfaceResourceList                         (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface);
 std::vector<std::string>                                                       getProgramInterfaceBlockMemberResourceList      (const glu::InterfaceBlock& interfaceBlock);
 glu::ProgramSources                                                                    generateProgramInterfaceProgramSources          (const ProgramInterfaceDefinition::Program* program);
 bool                                                                                           findProgramVariablePathByPathName                       (std::vector<ProgramInterfaceDefinition::VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const ProgramInterfaceDefinition::VariableSearchFilter& filter);
-void                                                                                           generateVariableTypeResourceNames                       (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, bool isTopLevelBufferVariable);
+void                                                                                           generateVariableTypeResourceNames                       (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags);
 ProgramInterfaceDefinition::ShaderResourceUsage                getShaderResourceUsage                                          (const ProgramInterfaceDefinition::Shader* shader);
 ProgramInterfaceDefinition::ProgramResourceUsage       getCombinedProgramResourceUsage                         (const ProgramInterfaceDefinition::Program* program);
 
index e9acce4..728d13a 100644 (file)
@@ -1323,49 +1323,39 @@ void TopLevelArrayStrideValidator::validateSingleVariable (const std::vector<Var
        }
 }
 
-class TransformFeedbackArraySizeValidator : public PropValidator
+class TransformFeedbackResourceValidator : public PropValidator
 {
 public:
-                               TransformFeedbackArraySizeValidator     (Context& context);
-       void            validate                                                        (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
+                                       TransformFeedbackResourceValidator      (Context& context, ProgramResourcePropFlags validationProp);
+       void                    validate                                                        (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const;
+
+private:
+       virtual void    validateBuiltinVariable                         (const std::string& resource, glw::GLint propValue) const = 0;
+       virtual void    validateSingleVariable                          (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const = 0;
 };
 
-TransformFeedbackArraySizeValidator::TransformFeedbackArraySizeValidator (Context& context)
-       : PropValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE)
+
+TransformFeedbackResourceValidator::TransformFeedbackResourceValidator (Context& context, ProgramResourcePropFlags validationProp)
+       : PropValidator(context, validationProp)
 {
 }
 
-void TransformFeedbackArraySizeValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
+void TransformFeedbackResourceValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue) const
 {
-       int arraySize = 0;
-
        if (deStringBeginsWith(resource.c_str(), "gl_"))
        {
-               if (resource == "gl_Position")
-                       arraySize = 1;
-               else
-                       DE_ASSERT(false);
-       }
-       else if (!stringEndsWith(resource, "[0]"))
-       {
-               // user-defined non-array. Just check it exists
-               std::vector<VariablePathComponent> path;
-               if (!findProgramVariablePathByPathName(path, program, resource, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
-               {
-                       DE_ASSERT(false);
-                       return;
-               }
-
-               arraySize = 1;
+               validateBuiltinVariable(resource, propValue);
        }
        else
        {
+               // Check resource name is a xfb output. (sanity check)
+#if defined(DE_DEBUG)
                bool generatorFound = false;
 
-               // user-defined, array or array element. Find the generating varying declaration
+               // Check the resource name is a valid transform feedback resource and find the name generating resource
                for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
                {
-                       const std::string                                       varyingName     = program->getTransformFeedbackVaryings()[varyingNdx];
+                       const std::string                                       varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
                        std::vector<VariablePathComponent>      path;
                        std::vector<std::string>                        resources;
 
@@ -1376,22 +1366,68 @@ void TransformFeedbackArraySizeValidator::validate (const ProgramInterfaceDefini
                                return;
                        }
 
-                       generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(), false);
+                       generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(), RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
 
                        if (de::contains(resources.begin(), resources.end(), resource))
                        {
-                               arraySize = (path.back().getVariableType()->isArrayType()) ? (path.back().getVariableType()->getArraySize()) : (1);
                                generatorFound = true;
                                break;
                        }
                }
 
-               if (!generatorFound)
+               // resource name was not found, should never happen
+               DE_ASSERT(generatorFound);
+               DE_UNREF(generatorFound);
+#endif
+
+               // verify resource
                {
-                       DE_ASSERT(false);
-                       return;
+                       std::vector<VariablePathComponent> path;
+
+                       if (!findProgramVariablePathByPathName(path, program, resource, VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT)))
+                               DE_ASSERT(false);
+
+                       validateSingleVariable(path, resource, propValue);
                }
        }
+}
+
+class TransformFeedbackArraySizeValidator : public TransformFeedbackResourceValidator
+{
+public:
+                               TransformFeedbackArraySizeValidator     (Context& context);
+
+       void            validateBuiltinVariable                         (const std::string& resource, glw::GLint propValue) const;
+       void            validateSingleVariable                          (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
+};
+
+TransformFeedbackArraySizeValidator::TransformFeedbackArraySizeValidator (Context& context)
+       : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE)
+{
+}
+
+void TransformFeedbackArraySizeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
+{
+       int arraySize = 0;
+
+       if (resource == "gl_Position")
+               arraySize = 1;
+       else
+               DE_ASSERT(false);
+
+       m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage;
+       if (arraySize != propValue)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
+               setError("resource array size invalid");
+       }
+}
+
+void TransformFeedbackArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
+{
+       DE_UNREF(resource);
+
+       const int arraySize = (path.back().getVariableType()->isArrayType()) ? (path.back().getVariableType()->getArraySize()) : (1);
 
        m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage;
        if (arraySize != propValue)
@@ -1401,6 +1437,96 @@ void TransformFeedbackArraySizeValidator::validate (const ProgramInterfaceDefini
        }
 }
 
+class TransformFeedbackNameLengthValidator : public TransformFeedbackResourceValidator
+{
+public:
+                               TransformFeedbackNameLengthValidator    (Context& context);
+
+private:
+       void            validateBuiltinVariable                                 (const std::string& resource, glw::GLint propValue) const;
+       void            validateSingleVariable                                  (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
+       void            validateVariable                                                (const std::string& resource, glw::GLint propValue) const;
+};
+
+TransformFeedbackNameLengthValidator::TransformFeedbackNameLengthValidator (Context& context)
+       : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH)
+{
+}
+
+void TransformFeedbackNameLengthValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
+{
+       validateVariable(resource, propValue);
+}
+
+void TransformFeedbackNameLengthValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
+{
+       DE_UNREF(path);
+       validateVariable(resource, propValue);
+}
+
+void TransformFeedbackNameLengthValidator::validateVariable (const std::string& resource, glw::GLint propValue) const
+{
+       const int expected = (int)resource.length() + 1; // includes null byte
+       m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)resource.length() << " for \"" << resource << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
+
+       if (propValue != expected)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage;
+               setError("name length invalid");
+       }
+}
+
+class TransformFeedbackTypeValidator : public TransformFeedbackResourceValidator
+{
+public:
+                               TransformFeedbackTypeValidator          (Context& context);
+
+       void            validateBuiltinVariable                         (const std::string& resource, glw::GLint propValue) const;
+       void            validateSingleVariable                          (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const;
+};
+
+TransformFeedbackTypeValidator::TransformFeedbackTypeValidator (Context& context)
+       : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_TYPE)
+{
+}
+
+void TransformFeedbackTypeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue) const
+{
+       glu::DataType varType = glu::TYPE_INVALID;
+
+       if (resource == "gl_Position")
+               varType = glu::TYPE_FLOAT_VEC4;
+       else
+               DE_ASSERT(false);
+
+       m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(varType) << tcu::TestLog::EndMessage;
+       if (glu::getDataTypeFromGLType(propValue) != varType)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
+               setError("resource type invalid");
+       }
+       return;
+}
+
+void TransformFeedbackTypeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue) const
+{
+       DE_UNREF(resource);
+
+       // Unlike other interfaces, xfb program interface uses just variable name to refer to arrays of basic types. (Others use "variable[0]")
+       // Thus we might end up querying a type for an array. In this case, return the type of an array element.
+       const glu::VarType& variable    = *path.back().getVariableType();
+       const glu::VarType& elementType = (variable.isArrayType()) ? (variable.getElementType()) : (variable);
+
+       DE_ASSERT(elementType.isBasicType());
+
+       m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(elementType.getBasicType()) << tcu::TestLog::EndMessage;
+       if (elementType.getBasicType() != glu::getDataTypeFromGLType(propValue))
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
+               setError("resource type invalid");
+       }
+}
+
 } // anonymous
 
 ProgramResourceQueryTestTarget::ProgramResourceQueryTestTarget (ProgramInterface interface_, deUint32 propFlags_)
@@ -1807,9 +1933,9 @@ ProgramInterfaceQueryTestCase::IterateResult ProgramInterfaceQueryTestCase::iter
 
                case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
                {
-                       const TypeValidator                                                     typeValidator                   (m_context, program.getProgram(), VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT));
+                       const TransformFeedbackTypeValidator            typeValidator                   (m_context);
                        const TransformFeedbackArraySizeValidator       arraySizeValidator              (m_context);
-                       const VariableNameLengthValidator                       nameLengthValidator             (m_context, program.getProgram(), VariableSearchFilter(glu::SHADERTYPE_VERTEX, glu::STORAGE_OUT));
+                       const TransformFeedbackNameLengthValidator      nameLengthValidator             (m_context);
 
                        const TestProperty allProperties[] =
                        {
index 28aff5e..cf22cb1 100644 (file)
@@ -5304,7 +5304,14 @@ static void generateTransformFeedbackVariableTypeBlockContents (Context& context
        const ResourceDefinition::Node::SharedPtr       output                  (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
        const ResourceDefinition::Node::SharedPtr       flatShading             (new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT));
 
-       // Only basic types, arrays of basic types, struct of basic types (and no booleans)
+       // Only builtins, basic types, arrays of basic types, struct of basic types (and no booleans)
+       {
+               const ResourceDefinition::Node::SharedPtr       xfbTarget               (new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
+               tcu::TestCaseGroup* const                                       blockGroup              = new TestCaseGroup(context, "builtin", "Built-in outputs");
+
+               targetGroup->addChild(blockGroup);
+               blockGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE), "gl_position"));
+       }
        {
                const ResourceDefinition::Node::SharedPtr       xfbTarget               (new ResourceDefinition::TransformFeedbackTarget(flatShading));
                tcu::TestCaseGroup* const                                       blockGroup              = new TestCaseGroup(context, "basic_type", "Basic types");
@@ -5321,6 +5328,14 @@ static void generateTransformFeedbackVariableTypeBlockContents (Context& context
                generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup);
        }
        {
+               const ResourceDefinition::Node::SharedPtr       xfbTarget               (new ResourceDefinition::TransformFeedbackTarget(flatShading));
+               const ResourceDefinition::Node::SharedPtr       arrayElement    (new ResourceDefinition::ArrayElement(xfbTarget));
+               tcu::TestCaseGroup* const                                       blockGroup              = new TestCaseGroup(context, "whole_array", "Whole array");
+
+               targetGroup->addChild(blockGroup);
+               generateTransformFeedbackVariableBasicTypeCases(context, arrayElement, blockGroup);
+       }
+       {
                const ResourceDefinition::Node::SharedPtr       structMember    (new ResourceDefinition::StructMember(flatShading));
                const ResourceDefinition::Node::SharedPtr       xfbTarget               (new ResourceDefinition::TransformFeedbackTarget(structMember));
                tcu::TestCaseGroup* const                                       blockGroup              = new TestCaseGroup(context, "struct", "Struct types");