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.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
new file mode 100644
index 0000000000..ac1c10d6b0
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateOutputs.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/ParseContext.h"
+
+ValidateOutputs::ValidateOutputs(TInfoSinkBase& sink, int maxDrawBuffers)
+ : mSink(sink),
+ mMaxDrawBuffers(maxDrawBuffers),
+ mNumErrors(0),
+ mHasUnspecifiedOutputLocation(false)
+{
+}
+
+void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+{
+ TString name = symbol->getSymbol();
+ TQualifier qualifier = symbol->getQualifier();
+
+ if (mVisitedSymbols.count(name) == 1)
+ return;
+
+ mVisitedSymbols.insert(name);
+
+ if (qualifier == EvqFragmentOut)
+ {
+ const TType &type = symbol->getType();
+ const int location = type.getLayoutQualifier().location;
+
+ if (mHasUnspecifiedOutputLocation)
+ {
+ error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str());
+ }
+ else if (location == -1)
+ {
+ mHasUnspecifiedOutputLocation = true;
+ }
+ else
+ {
+ OutputMap::iterator mapEntry = mOutputMap.find(location);
+ if (mapEntry == mOutputMap.end())
+ {
+ const int elementCount = type.isArray() ? type.getArraySize() : 1;
+ if (location + elementCount > mMaxDrawBuffers)
+ {
+ error(symbol->getLine(), "output location must be < MAX_DRAW_BUFFERS", name.c_str());
+ }
+
+ for (int elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ {
+ const int offsetLocation = location + elementIndex;
+ mOutputMap[offsetLocation] = symbol;
+ }
+ }
+ else
+ {
+ std::stringstream strstr;
+ strstr << "conflicting output locations with previously defined output '"
+ << mapEntry->second->getSymbol() << "'";
+
+ error(symbol->getLine(), strstr.str().c_str(), name.c_str());
+ }
+ }
+ }
+}
+
+void ValidateOutputs::error(TSourceLoc loc, const char *reason, const char* token)
+{
+ mSink.prefix(EPrefixError);
+ mSink.location(loc);
+ mSink << "'" << token << "' : " << reason << "\n";
+ mNumErrors++;
+}