blob: 6976309f14b26a0160a4b3982ec19975629cbbb6 [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),
Jamie Madill6d276c82015-07-20 19:00:38 +000017 mHasUnspecifiedOutputLocation(false)
Jamie Madill05a80ce2013-06-20 11:55:49 -040018{
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;
Kimmo Kinnunen8518e7f2015-07-16 14:54:08 +030035 const bool isUnspecifiedOutputLocation = location == -1;
Jamie Madill05a80ce2013-06-20 11:55:49 -040036
Kimmo Kinnunen8518e7f2015-07-16 14:54:08 +030037 if (mHasUnspecifiedOutputLocation || (isUnspecifiedOutputLocation && !mOutputMap.empty()))
Jamie Madill05a80ce2013-06-20 11:55:49 -040038 {
39 error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str());
40 }
Kimmo Kinnunen8518e7f2015-07-16 14:54:08 +030041 else if (isUnspecifiedOutputLocation)
Jamie Madill05a80ce2013-06-20 11:55:49 -040042 {
Jamie Madill6d276c82015-07-20 19:00:38 +000043 mHasUnspecifiedOutputLocation = true;
Jamie Madill05a80ce2013-06-20 11:55:49 -040044 }
45 else
46 {
47 OutputMap::iterator mapEntry = mOutputMap.find(location);
48 if (mapEntry == mOutputMap.end())
49 {
50 const int elementCount = type.isArray() ? type.getArraySize() : 1;
51 if (location + elementCount > mMaxDrawBuffers)
52 {
53 error(symbol->getLine(), "output location must be < MAX_DRAW_BUFFERS", name.c_str());
54 }
55
56 for (int elementIndex = 0; elementIndex < elementCount; elementIndex++)
57 {
58 const int offsetLocation = location + elementIndex;
59 mOutputMap[offsetLocation] = symbol;
60 }
61 }
62 else
63 {
64 std::stringstream strstr;
65 strstr << "conflicting output locations with previously defined output '"
66 << mapEntry->second->getSymbol() << "'";
67
68 error(symbol->getLine(), strstr.str().c_str(), name.c_str());
69 }
70 }
71 }
72}
73
74void ValidateOutputs::error(TSourceLoc loc, const char *reason, const char* token)
75{
76 mSink.prefix(EPrefixError);
77 mSink.location(loc);
78 mSink << "'" << token << "' : " << reason << "\n";
79 mNumErrors++;
80}