return false;
}
- if (spec.fullGLSLES100Required)
+ if (isCapabilityRequired(CAPABILITY_FULL_GLSL_ES_100_SUPPORT, spec))
{
if (spec.targetVersion != GLSL_VERSION_100_ES)
{
return true;
}
+bool isCapabilityRequired(CapabilityFlag capabilityFlag, const ShaderCaseSpecification& spec)
+{
+ std::vector<RequiredCapability>::const_iterator currRequirement = spec.requiredCaps.begin();
+ while (currRequirement != spec.requiredCaps.end())
+ {
+ if ((currRequirement->type == CAPABILITY_FLAG) && (currRequirement->flagName == capabilityFlag))
+ return true;
+ ++currRequirement;
+ }
+
+ return false;
+}
+
// Parser
static const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') || (c == '-') || (c == '.');
}
-struct CaseRequirement
-{
- enum Type
- {
- TYPE_EXTENSION = 0,
- TYPE_FULL_GLSL_ES_100_SUPPORT,
- TYPE_IMPLEMENTATION_LIMIT,
-
- TYPE_LAST
- };
-
- Type type;
-
- // TYPE_EXTENSION:
- RequiredExtension extension;
-
- // TYPE_IMPLEMENTATION_LIMIT
- RequiredCapability requiredCap;
-
- CaseRequirement (void) : type(TYPE_LAST) {}
-
- static CaseRequirement createFullGLSLES100SpecificationRequirement (void)
- {
- CaseRequirement req;
- req.type = TYPE_FULL_GLSL_ES_100_SUPPORT;
- return req;
- }
-
- static CaseRequirement createAnyExtensionRequirement (const vector<string>& alternatives, deUint32 effectiveStages)
- {
- CaseRequirement req;
- req.type = TYPE_EXTENSION;
- req.extension = RequiredExtension(alternatives, effectiveStages);
- return req;
- }
-
- static CaseRequirement createLimitRequirement (deUint32 enumName, int referenceValue)
- {
- CaseRequirement req;
- req.type = TYPE_IMPLEMENTATION_LIMIT;
- req.requiredCap = RequiredCapability(enumName, referenceValue);
- return req;
- }
-};
-
class ShaderParser
{
public:
void parseValue (ValueBlock& valueBlock);
void parseValueBlock (ValueBlock& valueBlock);
deUint32 parseShaderStageList (void);
- void parseRequirement (CaseRequirement& valueBlock);
+ void parseRequirement (vector<RequiredCapability> &requiredCaps, vector<RequiredExtension> &requiredExts);
void parseExpectResult (ExpectResult& expectResult);
void parseFormat (DataType& format);
void parseGLSLVersion (glu::GLSLVersion& version);
return mask;
}
-void ShaderParser::parseRequirement (CaseRequirement& valueBlock)
+void ShaderParser::parseRequirement (vector<RequiredCapability>& requiredCaps, vector<RequiredExtension>& requiredExts)
{
PARSE_DBG((" parseRequirement()\n"));
affectedCasesFlags = parseShaderStageList();
}
- valueBlock = CaseRequirement::createAnyExtensionRequirement(anyExtensionStringList, affectedCasesFlags);
+ requiredExts.push_back(RequiredExtension(anyExtensionStringList, affectedCasesFlags));
}
else if (m_curTokenStr == "limit")
{
limitValue = parseIntLiteral(m_curTokenStr.c_str());
advanceToken();
- valueBlock = CaseRequirement::createLimitRequirement(limitEnum, limitValue);
+ requiredCaps.push_back(RequiredCapability(limitEnum, limitValue));
}
else if (m_curTokenStr == "full_glsl_es_100_support")
{
advanceToken();
- valueBlock = CaseRequirement::createFullGLSLES100SpecificationRequirement();
+ requiredCaps.push_back(RequiredCapability(CAPABILITY_FULL_GLSL_ES_100_SUPPORT));
+ }
+ else if (m_curTokenStr == "only_glsl_es_100_support")
+ {
+ advanceToken();
+
+ requiredCaps.push_back(RequiredCapability(CAPABILITY_ONLY_GLSL_ES_100_SUPPORT));
+ }
+ else if (m_curTokenStr == "exactly_one_draw_buffer")
+ {
+ advanceToken();
+
+ requiredCaps.push_back(RequiredCapability(CAPABILITY_EXACTLY_ONE_DRAW_BUFFER));
}
else
parseError(string("invalid requirement value: " + m_curTokenStr));
}
else if (m_curToken == TOKEN_REQUIRE)
{
- CaseRequirement requirement;
- parseRequirement(requirement);
+ vector<RequiredCapability> dummyCaps;
+ size_t size = program.requiredExtensions.size();
+ parseRequirement(dummyCaps, program.requiredExtensions);
- if (requirement.type == CaseRequirement::TYPE_EXTENSION)
- program.requiredExtensions.push_back(requirement.extension);
- else
+ if (size == program.requiredExtensions.size())
parseError("only extension requirements are allowed inside pipeline program");
}
else if (m_curToken == TOKEN_VERTEX ||
vector<string> geometrySources;
ValueBlock valueBlock;
bool valueBlockSeen = false;
- vector<CaseRequirement> requirements;
+ vector<RequiredCapability> requiredCaps;
+ vector<RequiredExtension> requiredExts;
vector<ProgramSpecification> pipelinePrograms;
for (;;)
}
else if (m_curToken == TOKEN_REQUIRE)
{
- CaseRequirement requirement;
- parseRequirement(requirement);
- requirements.push_back(requirement);
+ parseRequirement(requiredCaps, requiredExts);
}
else if (m_curToken == TOKEN_PIPELINE_PROGRAM)
{
advanceToken(TOKEN_END); // case end
- // \todo [pyry] Clean up
- vector<RequiredCapability> requiredCaps;
- vector<RequiredExtension> requiredExts;
- bool fullGLSLES100Required = false;
-
- for (size_t reqNdx = 0; reqNdx < requirements.size(); ++reqNdx)
- {
- const CaseRequirement& requirement = requirements[reqNdx];
-
- if (requirement.type == CaseRequirement::TYPE_EXTENSION)
- requiredExts.push_back(requirement.extension);
- else if (requirement.type == CaseRequirement::TYPE_IMPLEMENTATION_LIMIT)
- requiredCaps.push_back(requirement.requiredCap);
- else if (requirement.type == CaseRequirement::TYPE_FULL_GLSL_ES_100_SUPPORT)
- fullGLSLES100Required = true;
- else
- DE_ASSERT(false);
- }
-
if (!bothSource.empty())
{
if (!vertexSources.empty() ||
spec.caseType = CASETYPE_VERTEX_ONLY;
spec.expectResult = expectResult;
spec.targetVersion = version;
- spec.fullGLSLES100Required = fullGLSLES100Required;
spec.requiredCaps = requiredCaps;
spec.values = valueBlock;
spec.caseType = CASETYPE_FRAGMENT_ONLY;
spec.expectResult = expectResult;
spec.targetVersion = version;
- spec.fullGLSLES100Required = fullGLSLES100Required;
spec.requiredCaps = requiredCaps;
spec.values = valueBlock;
spec.outputType = outputType;
spec.outputFormat = format;
spec.targetVersion = version;
- spec.fullGLSLES100Required = fullGLSLES100Required;
spec.requiredCaps = requiredCaps;
spec.values = valueBlock;
spec.caseType = CASETYPE_COMPLETE;
spec.expectResult = expectResult;
spec.targetVersion = version;
- spec.fullGLSLES100Required = fullGLSLES100Required;
spec.requiredCaps = requiredCaps;
spec.values = valueBlock;
std::vector<Value> uniforms;
};
+enum CapabilityType
+{
+ CAPABILITY_LIMIT = 0,
+ CAPABILITY_FLAG,
+
+ CAPABILITY_LAST
+};
+
+enum CapabilityFlag
+{
+ CAPABILITY_FULL_GLSL_ES_100_SUPPORT,
+ CAPABILITY_ONLY_GLSL_ES_100_SUPPORT, // only ES2, no ES3 capability
+ CAPABILITY_EXACTLY_ONE_DRAW_BUFFER // gl_MaxDrawBuffers is exactly 1
+};
+
struct RequiredCapability
{
- deUint32 enumName;
+ CapabilityType type;
+
+ union
+ {
+ CapabilityFlag flagName;
+ deUint32 enumName;
+ };
+
int referenceValue;
- RequiredCapability (void)
- : enumName (0u)
- , referenceValue (0)
+ RequiredCapability (CapabilityFlag flagName_)
+ : type (CAPABILITY_FLAG)
+ , flagName (flagName_)
+ , referenceValue (0) // not used
{
}
RequiredCapability (deUint32 enumName_, int referenceValue_)
- : enumName (enumName_)
+ : type (CAPABILITY_LIMIT)
+ , enumName (enumName_)
, referenceValue (referenceValue_)
{
}
DataType outputFormat;
glu::GLSLVersion targetVersion;
- // \todo [pyry] Clean this up
std::vector<RequiredCapability> requiredCaps;
- bool fullGLSLES100Required;
ValueBlock values;
std::vector<ProgramSpecification> programs;
, outputType (OUTPUT_RESULT)
, outputFormat (TYPE_LAST)
, targetVersion (glu::GLSL_VERSION_LAST)
- , fullGLSLES100Required (false)
{
}
};
bool isValid (const ValueBlock& block);
bool isValid (const ShaderCaseSpecification& spec);
+bool isCapabilityRequired(CapabilityFlag capabilityFlag, const ShaderCaseSpecification& spec);
+
class ShaderCaseFactory
{
public:
{
for (size_t capNdx = 0; capNdx < requiredCaps.size(); ++capNdx)
{
- const deUint32 pname = requiredCaps[capNdx].enumName;
- const int requiredValue = requiredCaps[capNdx].referenceValue;
+ const RequiredCapability& capability = requiredCaps[capNdx];
+ if (capability.type != CAPABILITY_LIMIT)
+ continue;
+
+ const deUint32 pname = capability.enumName;
+ const int requiredValue = capability.referenceValue;
const int supportedValue = ctxInfo.getInt((int)pname);
if (supportedValue <= requiredValue)
GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderCase::execute(): start");
+ if(isCapabilityRequired(CAPABILITY_ONLY_GLSL_ES_100_SUPPORT, m_spec))
+ {
+ // GL_MAJOR_VERSION query does not exist on GLES2
+ // so succeeding query implies GLES3+ hardware.
+ glw::GLint majorVersion = 0;
+ gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
+ if (gl.getError() == GL_NO_ERROR)
+ return true;
+ }
+
+ if(isCapabilityRequired(CAPABILITY_EXACTLY_ONE_DRAW_BUFFER, m_spec))
+ {
+ // on unextended ES2 there is only one draw buffer
+ // and there is no GL_MAX_DRAW_BUFFERS query
+ glw::GLint maxDrawBuffers = 0;
+ gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
+ if ((gl.getError() == GL_NO_ERROR) && (maxDrawBuffers > 1))
+ throw tcu::NotSupportedError("Test requires exactly one draw buffer");
+ }
+
// Specialize shaders
if (m_spec.caseType == CASETYPE_VERTEX_ONLY)
{
// \todo [2010-06-07 petri] These should be handled in the test case?
log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
- if (m_spec.fullGLSLES100Required)
+ if (isCapabilityRequired(CAPABILITY_FULL_GLSL_ES_100_SUPPORT, m_spec))
{
log << TestLog::Message
<< "Assuming build failure is caused by implementation not supporting full GLSL ES 100 specification, which is not required."