blob: 733fe9ac733cbebd2633bef2efc360d9354da6c8 [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{
Olli Etuaho77ba4082016-12-16 12:01:18 +000017void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030018{
Olli Etuaho77ba4082016-12-16 12:01:18 +000019 diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030020}
21
22} // namespace
23
24ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030025 : TIntermTraverser(true, false, false),
Jamie Madill05a80ce2013-06-20 11:55:49 -040026 mMaxDrawBuffers(maxDrawBuffers),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030027 mAllowUnspecifiedOutputLocationResolution(
Andrei Volykhina5527072017-03-22 16:46:30 +030028 IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended")),
29 mUsesFragDepth(false)
Jamie Madill05a80ce2013-06-20 11:55:49 -040030{
31}
32
33void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
34{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050035 TString name = symbol->getSymbol();
Jamie Madill05a80ce2013-06-20 11:55:49 -040036 TQualifier qualifier = symbol->getQualifier();
37
Jamie Madill5ed23982016-04-22 15:08:57 -040038 if (mVisitedSymbols.count(name.c_str()) == 1)
Jamie Madill05a80ce2013-06-20 11:55:49 -040039 return;
40
Jamie Madill5ed23982016-04-22 15:08:57 -040041 mVisitedSymbols.insert(name.c_str());
Jamie Madill05a80ce2013-06-20 11:55:49 -040042
Jamie Madill19571812013-08-12 15:26:34 -070043 if (qualifier == EvqFragmentOut)
Jamie Madill05a80ce2013-06-20 11:55:49 -040044 {
Andrei Volykhina5527072017-03-22 16:46:30 +030045 if (symbol->getType().getLayoutQualifier().location != -1)
Jamie Madill05a80ce2013-06-20 11:55:49 -040046 {
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030047 mOutputs.push_back(symbol);
Jamie Madill05a80ce2013-06-20 11:55:49 -040048 }
Andrei Volykhina5527072017-03-22 16:46:30 +030049 else if (symbol->getType().getLayoutQualifier().yuv == true)
50 {
51 mYuvOutputs.push_back(symbol);
52 }
53 else
54 {
55 mUnspecifiedLocationOutputs.push_back(symbol);
56 }
57 }
58 else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT)
59 {
60 mUsesFragDepth = true;
Jamie Madill05a80ce2013-06-20 11:55:49 -040061 }
62}
63
Olli Etuaho77ba4082016-12-16 12:01:18 +000064void ValidateOutputs::validate(TDiagnostics *diagnostics) const
Jamie Madill05a80ce2013-06-20 11:55:49 -040065{
Olli Etuaho77ba4082016-12-16 12:01:18 +000066 ASSERT(diagnostics);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030067 OutputVector validOutputs(mMaxDrawBuffers);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030068
69 for (const auto &symbol : mOutputs)
70 {
71 const TType &type = symbol->getType();
Olli Etuaho856c4972016-08-08 11:38:39 +030072 const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1u);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030073 const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
74
75 ASSERT(type.getLayoutQualifier().location != -1);
76
77 if (location + elementCount <= validOutputs.size())
78 {
79 for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
80 {
81 const size_t offsetLocation = location + elementIndex;
82 if (validOutputs[offsetLocation])
83 {
84 std::stringstream strstr;
85 strstr << "conflicting output locations with previously defined output '"
86 << validOutputs[offsetLocation]->getSymbol() << "'";
Olli Etuaho77ba4082016-12-16 12:01:18 +000087 error(*symbol, strstr.str().c_str(), diagnostics);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030088 }
89 else
90 {
91 validOutputs[offsetLocation] = symbol;
92 }
93 }
94 }
95 else
96 {
97 if (elementCount > 0)
98 {
Olli Etuaho77ba4082016-12-16 12:01:18 +000099 error(*symbol,
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300100 elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
Olli Etuaho77ba4082016-12-16 12:01:18 +0000101 : "output location must be < MAX_DRAW_BUFFERS",
102 diagnostics);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300103 }
104 }
105 }
106
107 if (!mAllowUnspecifiedOutputLocationResolution &&
108 ((!mOutputs.empty() && !mUnspecifiedLocationOutputs.empty()) ||
109 mUnspecifiedLocationOutputs.size() > 1))
110 {
111 for (const auto &symbol : mUnspecifiedLocationOutputs)
112 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000113 error(*symbol,
114 "must explicitly specify all locations when using multiple fragment outputs",
115 diagnostics);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300116 }
117 }
Andrei Volykhina5527072017-03-22 16:46:30 +0300118
119 if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() ||
120 !mUnspecifiedLocationOutputs.empty()))
121 {
122 for (const auto &symbol : mYuvOutputs)
123 {
124 error(*symbol,
125 "not allowed to specify yuv qualifier when using depth or multiple color "
126 "fragment outputs",
127 diagnostics);
128 }
129 }
Jamie Madill05a80ce2013-06-20 11:55:49 -0400130}
Jamie Madill45bcc782016-11-07 13:58:48 -0500131
132} // namespace sh