""
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
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
}
}
-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));
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;
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;
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;
}
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)
{
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)
{
{
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;
} // 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);
}
}
-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;
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)
}
}
+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_)
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[] =
{
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");
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");