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.cpp116
1 files changed, 91 insertions, 25 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
index cd37aeacd1..26f0e81ba7 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -3,64 +3,101 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations,
+// out-of-range locations, that locations are specified when using multiple outputs, and YUV output
+// validity.
#include "compiler/translator/ValidateOutputs.h"
+
+#include <set>
+
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h"
+namespace sh
+{
+
namespace
{
-void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason)
+void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
{
- sink.prefix(EPrefixError);
- sink.location(symbol.getLine());
- sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
- (*errorCount)++;
+ diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
}
-} // namespace
+class ValidateOutputsTraverser : public TIntermTraverser
+{
+ public:
+ ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
+
+ void validate(TDiagnostics *diagnostics) const;
+
+ void visitSymbol(TIntermSymbol *) override;
-ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
+ private:
+ int mMaxDrawBuffers;
+ bool mAllowUnspecifiedOutputLocationResolution;
+ bool mUsesFragDepth;
+
+ typedef std::vector<TIntermSymbol *> OutputVector;
+ OutputVector mOutputs;
+ OutputVector mUnspecifiedLocationOutputs;
+ OutputVector mYuvOutputs;
+ std::set<std::string> mVisitedSymbols;
+};
+
+ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior,
+ int maxDrawBuffers)
: TIntermTraverser(true, false, false),
mMaxDrawBuffers(maxDrawBuffers),
mAllowUnspecifiedOutputLocationResolution(
- IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
+ IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)),
+ mUsesFragDepth(false)
{
}
-void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol)
{
- TString name = symbol->getSymbol();
+ TString name = symbol->getSymbol();
TQualifier qualifier = symbol->getQualifier();
- if (mVisitedSymbols.count(name) == 1)
+ if (mVisitedSymbols.count(name.c_str()) == 1)
return;
- mVisitedSymbols.insert(name);
+ mVisitedSymbols.insert(name.c_str());
if (qualifier == EvqFragmentOut)
{
- if (symbol->getType().getLayoutQualifier().location == -1)
+ if (symbol->getType().getLayoutQualifier().location != -1)
{
- mUnspecifiedLocationOutputs.push_back(symbol);
+ mOutputs.push_back(symbol);
+ }
+ else if (symbol->getType().getLayoutQualifier().yuv == true)
+ {
+ mYuvOutputs.push_back(symbol);
}
else
{
- mOutputs.push_back(symbol);
+ mUnspecifiedLocationOutputs.push_back(symbol);
}
}
+ else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT)
+ {
+ mUsesFragDepth = true;
+ }
}
-int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
+void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
{
+ ASSERT(diagnostics);
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);
+ ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6.
+ const size_t elementCount =
+ static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
ASSERT(type.getLayoutQualifier().location != -1);
@@ -75,7 +112,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
std::stringstream strstr;
strstr << "conflicting output locations with previously defined output '"
<< validOutputs[offsetLocation]->getSymbol() << "'";
- error(&errorCount, sink, *symbol, strstr.str().c_str());
+ error(*symbol, strstr.str().c_str(), diagnostics);
}
else
{
@@ -87,9 +124,10 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{
if (elementCount > 0)
{
- error(&errorCount, sink, *symbol,
+ error(*symbol,
elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
- : "output location must be < MAX_DRAW_BUFFERS");
+ : "output location must be < MAX_DRAW_BUFFERS",
+ diagnostics);
}
}
}
@@ -100,9 +138,37 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{
for (const auto &symbol : mUnspecifiedLocationOutputs)
{
- error(&errorCount, sink, *symbol,
- "must explicitly specify all locations when using multiple fragment outputs");
+ error(*symbol,
+ "must explicitly specify all locations when using multiple fragment outputs",
+ diagnostics);
}
}
- return errorCount;
+
+ if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() ||
+ !mUnspecifiedLocationOutputs.empty()))
+ {
+ for (const auto &symbol : mYuvOutputs)
+ {
+ error(*symbol,
+ "not allowed to specify yuv qualifier when using depth or multiple color "
+ "fragment outputs",
+ diagnostics);
+ }
+ }
+}
+
+} // anonymous namespace
+
+bool ValidateOutputs(TIntermBlock *root,
+ const TExtensionBehavior &extBehavior,
+ int maxDrawBuffers,
+ TDiagnostics *diagnostics)
+{
+ ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers);
+ root->traverse(&validateOutputs);
+ int numErrorsBefore = diagnostics->numErrors();
+ validateOutputs.validate(diagnostics);
+ return (diagnostics->numErrors() == numErrorsBefore);
}
+
+} // namespace sh