Reduce and verify fragment output PIQ test draw buffer usage.
- Check GL_MAX_DRAW_BUFFERS implementation limit and usage if shader
build fails.
- Reduce required GL_MAX_DRAW_BUFFERS from 5 to 4 in explicit location
fragment output array tests.
- Fix various max binding resource usage checks.
Bug: 18094242
Change-Id: I17e091eb1939fd7ec94789be70be5a069970b697
diff --git a/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp b/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp
index ccc0d80..5dca33b 100644
--- a/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.cpp
@@ -893,6 +893,35 @@
return numComponents;
}
+static int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader)
+{
+ DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT);
+
+ int maxOutputLocation = -1;
+
+ for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
+ {
+ if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
+ {
+ // missing location qualifier means location == 0
+ const int outputLocation = (shader->getDefaultBlock().variables[ndx].layout.location == -1)
+ ? (0)
+ : (shader->getDefaultBlock().variables[ndx].layout.location);
+
+ // only basic types or arrays of basic types possible
+ DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType());
+
+ const int locationSlotsTaken = (shader->getDefaultBlock().variables[ndx].varType.isArrayType())
+ ? (shader->getDefaultBlock().variables[ndx].varType.getArraySize())
+ : (1);
+
+ maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1);
+ }
+ }
+
+ return maxOutputLocation;
+}
+
} // anonymous
std::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock)
@@ -1315,27 +1344,28 @@
{
ProgramInterfaceDefinition::ProgramResourceUsage retVal;
- retVal.uniformBufferMaxBinding = 0;
+ retVal.uniformBufferMaxBinding = -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value
retVal.uniformBufferMaxSize = 0;
retVal.numUniformBlocks = 0;
retVal.numCombinedVertexUniformComponents = 0;
retVal.numCombinedFragmentUniformComponents = 0;
- retVal.shaderStorageBufferMaxBinding = 0;
+ retVal.shaderStorageBufferMaxBinding = -1; // see above
retVal.shaderStorageBufferMaxSize = 0;
retVal.numShaderStorageBlocks = 0;
retVal.numVaryingComponents = 0;
retVal.numVaryingVectors = 0;
retVal.numCombinedSamplers = 0;
- retVal.atomicCounterBufferMaxBinding = 0;
+ retVal.atomicCounterBufferMaxBinding = -1; // see above
retVal.atomicCounterBufferMaxSize = 0;
retVal.numAtomicCounterBuffers = 0;
retVal.numAtomicCounters = 0;
- retVal.maxImageBinding = 0;
+ retVal.maxImageBinding = -1; // see above
retVal.numCombinedImages = 0;
retVal.numCombinedOutputResources = 0;
retVal.numXFBInterleavedComponents = 0;
retVal.numXFBSeparateAttribs = 0;
retVal.numXFBSeparateComponents = 0;
+ retVal.fragmentOutputMaxBinding = -1; // see above
for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
{
@@ -1372,8 +1402,12 @@
retVal.numCombinedOutputResources += getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
retVal.numCombinedOutputResources += getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
+
if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
+ {
retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT);
+ retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader));
+ }
}
if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS)
diff --git a/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp b/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp
index 0117013..ac24fce 100644
--- a/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp
+++ b/modules/gles31/functional/es31fProgramInterfaceDefinitionUtil.hpp
@@ -147,6 +147,7 @@
int numXFBInterleavedComponents;
int numXFBSeparateAttribs;
int numXFBSeparateComponents;
+ int fragmentOutputMaxBinding;
};
} // ProgramInterfaceDefinition
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
index 728d13a..a8a86e9 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
@@ -2117,7 +2117,7 @@
{ GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, usage.atomicCounterBufferMaxSize },
{ GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers },
{ GL_MAX_COMBINED_ATOMIC_COUNTERS, usage.numAtomicCounters },
- { GL_MAX_IMAGE_UNITS, usage.maxImageBinding },
+ { GL_MAX_IMAGE_UNITS, usage.maxImageBinding+1 },
{ GL_MAX_COMBINED_IMAGE_UNIFORMS, usage.numCombinedImages },
{ GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, usage.shaderStorageBufferMaxBinding+1 },
{ GL_MAX_SHADER_STORAGE_BLOCK_SIZE, usage.shaderStorageBufferMaxSize },
@@ -2125,6 +2125,7 @@
{ GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, usage.numXFBInterleavedComponents },
{ GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, usage.numXFBSeparateAttribs },
{ GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, usage.numXFBSeparateComponents },
+ { GL_MAX_DRAW_BUFFERS, usage.fragmentOutputMaxBinding+1 },
};
bool allOk = true;
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
index cf22cb1..1df5f89 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
@@ -4839,7 +4839,7 @@
}
// .var_array_explicit_location
{
- const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
+ const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(1)));
const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));