blob: e48da8a79770d6025e667ecd12b9e5f780858084 [file] [log] [blame]
Jamie Madill05a80ce2013-06-20 11:55:49 -04001//
2// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/ValidateOutputs.h"
8#include "compiler/translator/InfoSink.h"
9#include "compiler/translator/InitializeParseContext.h"
Jamie Madill6b9cb252013-10-17 10:45:47 -040010#include "compiler/translator/ParseContext.h"
Jamie Madill05a80ce2013-06-20 11:55:49 -040011
Jamie Madill45bcc782016-11-07 13:58:48 -050012namespace sh
13{
14
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030015namespace
16{
17void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason)
18{
19 sink.prefix(EPrefixError);
20 sink.location(symbol.getLine());
21 sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
22 (*errorCount)++;
23}
24
25} // namespace
26
27ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030028 : TIntermTraverser(true, false, false),
Jamie Madill05a80ce2013-06-20 11:55:49 -040029 mMaxDrawBuffers(maxDrawBuffers),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030030 mAllowUnspecifiedOutputLocationResolution(
31 IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
Jamie Madill05a80ce2013-06-20 11:55:49 -040032{
33}
34
35void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
36{
37 TString name = symbol->getSymbol();
38 TQualifier qualifier = symbol->getQualifier();
39
Jamie Madill5ed23982016-04-22 15:08:57 -040040 if (mVisitedSymbols.count(name.c_str()) == 1)
Jamie Madill05a80ce2013-06-20 11:55:49 -040041 return;
42
Jamie Madill5ed23982016-04-22 15:08:57 -040043 mVisitedSymbols.insert(name.c_str());
Jamie Madill05a80ce2013-06-20 11:55:49 -040044
Jamie Madill19571812013-08-12 15:26:34 -070045 if (qualifier == EvqFragmentOut)
Jamie Madill05a80ce2013-06-20 11:55:49 -040046 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030047 if (symbol->getType().getLayoutQualifier().location == -1)
Jamie Madill05a80ce2013-06-20 11:55:49 -040048 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030049 mUnspecifiedLocationOutputs.push_back(symbol);
Jamie Madill05a80ce2013-06-20 11:55:49 -040050 }
51 else
52 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030053 mOutputs.push_back(symbol);
Jamie Madill05a80ce2013-06-20 11:55:49 -040054 }
55 }
56}
57
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030058int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
Jamie Madill05a80ce2013-06-20 11:55:49 -040059{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030060 OutputVector validOutputs(mMaxDrawBuffers);
61 int errorCount = 0;
62
63 for (const auto &symbol : mOutputs)
64 {
65 const TType &type = symbol->getType();
Olli Etuaho856c4972016-08-08 11:38:39 +030066 const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1u);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030067 const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
68
69 ASSERT(type.getLayoutQualifier().location != -1);
70
71 if (location + elementCount <= validOutputs.size())
72 {
73 for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
74 {
75 const size_t offsetLocation = location + elementIndex;
76 if (validOutputs[offsetLocation])
77 {
78 std::stringstream strstr;
79 strstr << "conflicting output locations with previously defined output '"
80 << validOutputs[offsetLocation]->getSymbol() << "'";
81 error(&errorCount, sink, *symbol, strstr.str().c_str());
82 }
83 else
84 {
85 validOutputs[offsetLocation] = symbol;
86 }
87 }
88 }
89 else
90 {
91 if (elementCount > 0)
92 {
93 error(&errorCount, sink, *symbol,
94 elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
95 : "output location must be < MAX_DRAW_BUFFERS");
96 }
97 }
98 }
99
100 if (!mAllowUnspecifiedOutputLocationResolution &&
101 ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) ||
102 mUnspecifiedLocationOutputs.size() > 1))
103 {
104 for (const auto &symbol : mUnspecifiedLocationOutputs)
105 {
106 error(&errorCount, sink, *symbol,
107 "must explicitly specify all locations when using multiple fragment outputs");
108 }
109 }
110 return errorCount;
Jamie Madill05a80ce2013-06-20 11:55:49 -0400111}
Jamie Madill45bcc782016-11-07 13:58:48 -0500112
113} // namespace sh