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