summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/compiler/translator/ValidateOutputs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/compiler/translator/ValidateOutputs.cpp')
-rwxr-xr-xgfx/angle/src/compiler/translator/ValidateOutputs.cpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/gfx/angle/src/compiler/translator/ValidateOutputs.cpp b/gfx/angle/src/compiler/translator/ValidateOutputs.cpp
new file mode 100755
index 000000000..e48da8a79
--- /dev/null
+++ b/gfx/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -0,0 +1,113 @@
+//
+// 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"
+
+namespace sh
+{
+
+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),
+ mAllowUnspecifiedOutputLocationResolution(
+ IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
+{
+}
+
+void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+{
+ TString name = symbol->getSymbol();
+ TQualifier qualifier = symbol->getQualifier();
+
+ if (mVisitedSymbols.count(name.c_str()) == 1)
+ return;
+
+ mVisitedSymbols.insert(name.c_str());
+
+ if (qualifier == EvqFragmentOut)
+ {
+ if (symbol->getType().getLayoutQualifier().location == -1)
+ {
+ mUnspecifiedLocationOutputs.push_back(symbol);
+ }
+ else
+ {
+ mOutputs.push_back(symbol);
+ }
+ }
+}
+
+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() : 1u);
+ const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
+
+ ASSERT(type.getLayoutQualifier().location != -1);
+
+ if (location + elementCount <= validOutputs.size())
+ {
+ for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ {
+ const size_t offsetLocation = location + elementIndex;
+ if (validOutputs[offsetLocation])
+ {
+ std::stringstream strstr;
+ strstr << "conflicting output locations with previously defined output '"
+ << validOutputs[offsetLocation]->getSymbol() << "'";
+ error(&errorCount, sink, *symbol, strstr.str().c_str());
+ }
+ else
+ {
+ validOutputs[offsetLocation] = symbol;
+ }
+ }
+ }
+ else
+ {
+ if (elementCount > 0)
+ {
+ error(&errorCount, sink, *symbol,
+ elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
+ : "output location must be < MAX_DRAW_BUFFERS");
+ }
+ }
+ }
+
+ 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;
+}
+
+} // namespace sh