blob: 614d790422ccacad0eb8c3750c7c2a0922360eaa [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
12ValidateOutputs::ValidateOutputs(TInfoSinkBase& sink, int maxDrawBuffers)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030013 : TIntermTraverser(true, false, false),
14 mSink(sink),
Jamie Madill05a80ce2013-06-20 11:55:49 -040015 mMaxDrawBuffers(maxDrawBuffers),
16 mNumErrors(0),
17 mHasUnspecifiedOutputLocation(false)
18{
19}
20
21void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
22{
23 TString name = symbol->getSymbol();
24 TQualifier qualifier = symbol->getQualifier();
25
26 if (mVisitedSymbols.count(name) == 1)
27 return;
28
29 mVisitedSymbols.insert(name);
30
Jamie Madill19571812013-08-12 15:26:34 -070031 if (qualifier == EvqFragmentOut)
Jamie Madill05a80ce2013-06-20 11:55:49 -040032 {
33 const TType &type = symbol->getType();
34 const int location = type.getLayoutQualifier().location;
35
36 if (mHasUnspecifiedOutputLocation)
37 {
38 error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str());
39 }
40 else if (location == -1)
41 {
42 mHasUnspecifiedOutputLocation = true;
43 }
44 else
45 {
46 OutputMap::iterator mapEntry = mOutputMap.find(location);
47 if (mapEntry == mOutputMap.end())
48 {
49 const int elementCount = type.isArray() ? type.getArraySize() : 1;
50 if (location + elementCount > mMaxDrawBuffers)
51 {
52 error(symbol->getLine(), "output location must be < MAX_DRAW_BUFFERS", name.c_str());
53 }
54
55 for (int elementIndex = 0; elementIndex < elementCount; elementIndex++)
56 {
57 const int offsetLocation = location + elementIndex;
58 mOutputMap[offsetLocation] = symbol;
59 }
60 }
61 else
62 {
63 std::stringstream strstr;
64 strstr << "conflicting output locations with previously defined output '"
65 << mapEntry->second->getSymbol() << "'";
66
67 error(symbol->getLine(), strstr.str().c_str(), name.c_str());
68 }
69 }
70 }
71}
72
73void ValidateOutputs::error(TSourceLoc loc, const char *reason, const char* token)
74{
75 mSink.prefix(EPrefixError);
76 mSink.location(loc);
77 mSink << "'" << token << "' : " << reason << "\n";
78 mNumErrors++;
79}