summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp98
1 files changed, 64 insertions, 34 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
index ac1c10d6b0..cd37aeacd1 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -9,11 +9,23 @@
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/ParseContext.h"
-ValidateOutputs::ValidateOutputs(TInfoSinkBase& sink, int maxDrawBuffers)
- : mSink(sink),
+namespace
+{
+void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason)
+{
+ sink.prefix(EPrefixError);
+ sink.location(symbol.getLine());
+ sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
+ (*errorCount)++;
+}
+
+} // namespace
+
+ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
+ : TIntermTraverser(true, false, false),
mMaxDrawBuffers(maxDrawBuffers),
- mNumErrors(0),
- mHasUnspecifiedOutputLocation(false)
+ mAllowUnspecifiedOutputLocationResolution(
+ IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
{
}
@@ -29,50 +41,68 @@ void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
if (qualifier == EvqFragmentOut)
{
- const TType &type = symbol->getType();
- const int location = type.getLayoutQualifier().location;
-
- if (mHasUnspecifiedOutputLocation)
+ if (symbol->getType().getLayoutQualifier().location == -1)
{
- error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str());
+ mUnspecifiedLocationOutputs.push_back(symbol);
}
- else if (location == -1)
+ else
{
- mHasUnspecifiedOutputLocation = true;
+ mOutputs.push_back(symbol);
}
- else
+ }
+}
+
+int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
+{
+ OutputVector validOutputs(mMaxDrawBuffers);
+ int errorCount = 0;
+
+ for (const auto &symbol : mOutputs)
+ {
+ const TType &type = symbol->getType();
+ const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1);
+ const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
+
+ ASSERT(type.getLayoutQualifier().location != -1);
+
+ if (location + elementCount <= validOutputs.size())
{
- OutputMap::iterator mapEntry = mOutputMap.find(location);
- if (mapEntry == mOutputMap.end())
+ for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
{
- const int elementCount = type.isArray() ? type.getArraySize() : 1;
- if (location + elementCount > mMaxDrawBuffers)
+ const size_t offsetLocation = location + elementIndex;
+ if (validOutputs[offsetLocation])
{
- error(symbol->getLine(), "output location must be < MAX_DRAW_BUFFERS", name.c_str());
+ std::stringstream strstr;
+ strstr << "conflicting output locations with previously defined output '"
+ << validOutputs[offsetLocation]->getSymbol() << "'";
+ error(&errorCount, sink, *symbol, strstr.str().c_str());
}
-
- for (int elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ else
{
- const int offsetLocation = location + elementIndex;
- mOutputMap[offsetLocation] = symbol;
+ validOutputs[offsetLocation] = symbol;
}
}
- else
+ }
+ else
+ {
+ if (elementCount > 0)
{
- std::stringstream strstr;
- strstr << "conflicting output locations with previously defined output '"
- << mapEntry->second->getSymbol() << "'";
-
- error(symbol->getLine(), strstr.str().c_str(), name.c_str());
+ error(&errorCount, sink, *symbol,
+ elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
+ : "output location must be < MAX_DRAW_BUFFERS");
}
}
}
-}
-void ValidateOutputs::error(TSourceLoc loc, const char *reason, const char* token)
-{
- mSink.prefix(EPrefixError);
- mSink.location(loc);
- mSink << "'" << token << "' : " << reason << "\n";
- mNumErrors++;
+ if (!mAllowUnspecifiedOutputLocationResolution &&
+ ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) ||
+ mUnspecifiedLocationOutputs.size() > 1))
+ {
+ for (const auto &symbol : mUnspecifiedLocationOutputs)
+ {
+ error(&errorCount, sink, *symbol,
+ "must explicitly specify all locations when using multiple fragment outputs");
+ }
+ }
+ return errorCount;
}