blob: 8cb50ae1886935bc921c57721de0ab004f6c96b0 [file] [log] [blame]
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001//
2// Copyright (c) 2002-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/translator/InitializeVariables.h"
Olli Etuahod57e0db2015-04-24 15:05:08 +03008
Zhenyao Mo72111912016-07-20 17:45:56 -07009#include "angle_gl.h"
Olli Etuahod57e0db2015-04-24 15:05:08 +030010#include "common/debug.h"
Zhenyao Mo72111912016-07-20 17:45:56 -070011#include "compiler/translator/IntermNode.h"
Zhenyao Mod7490962016-11-09 15:49:51 -080012#include "compiler/translator/SymbolTable.h"
Zhenyao Mo72111912016-07-20 17:45:56 -070013#include "compiler/translator/util.h"
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080014
Jamie Madill45bcc782016-11-07 13:58:48 -050015namespace sh
16{
17
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080018namespace
19{
20
Zhenyao Mo72111912016-07-20 17:45:56 -070021class VariableInitializer : public TIntermTraverser
22{
23 public:
Zhenyao Mod7490962016-11-09 15:49:51 -080024 VariableInitializer(const InitVariableList &vars, const TSymbolTable &symbolTable)
25 : TIntermTraverser(true, false, false),
26 mVariables(vars),
27 mSymbolTable(symbolTable),
28 mCodeInserted(false)
Zhenyao Mo72111912016-07-20 17:45:56 -070029 {
Zhenyao Mod7490962016-11-09 15:49:51 -080030 ASSERT(mSymbolTable.atGlobalLevel());
Zhenyao Mo72111912016-07-20 17:45:56 -070031 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080032
Zhenyao Mo72111912016-07-20 17:45:56 -070033 protected:
34 bool visitBinary(Visit, TIntermBinary *node) override { return false; }
35 bool visitUnary(Visit, TIntermUnary *node) override { return false; }
Olli Etuaho57961272016-09-14 13:57:46 +030036 bool visitIfElse(Visit, TIntermIfElse *node) override { return false; }
Zhenyao Mo72111912016-07-20 17:45:56 -070037 bool visitLoop(Visit, TIntermLoop *node) override { return false; }
38 bool visitBranch(Visit, TIntermBranch *node) override { return false; }
Olli Etuaho336b1472016-10-05 16:37:55 +010039 bool visitAggregate(Visit, TIntermAggregate *node) override { return false; }
Zhenyao Mo72111912016-07-20 17:45:56 -070040
Olli Etuaho336b1472016-10-05 16:37:55 +010041 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
Zhenyao Mo72111912016-07-20 17:45:56 -070042
43 private:
44 void insertInitCode(TIntermSequence *sequence);
45
46 const InitVariableList &mVariables;
Zhenyao Mod7490962016-11-09 15:49:51 -080047 const TSymbolTable &mSymbolTable;
Zhenyao Mo72111912016-07-20 17:45:56 -070048 bool mCodeInserted;
49};
50
51// VariableInitializer implementation.
52
Olli Etuaho336b1472016-10-05 16:37:55 +010053bool VariableInitializer::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080054{
Olli Etuaho336b1472016-10-05 16:37:55 +010055 // Function definition.
56 ASSERT(visit == PreVisit);
57 if (node->getFunctionSymbolInfo()->isMain())
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080058 {
Olli Etuaho336b1472016-10-05 16:37:55 +010059 TIntermBlock *body = node->getBody();
60 insertInitCode(body->getSequence());
61 mCodeInserted = true;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080062 }
Olli Etuaho336b1472016-10-05 16:37:55 +010063 return false;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080064}
65
Zhenyao Mo72111912016-07-20 17:45:56 -070066void VariableInitializer::insertInitCode(TIntermSequence *sequence)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080067{
Corentin Wallez509e4562016-08-25 14:55:44 -040068 for (const auto &var : mVariables)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080069 {
Zhenyao Mo72111912016-07-20 17:45:56 -070070 TString name = TString(var.name.c_str());
Corentin Wallez509e4562016-08-25 14:55:44 -040071
Zhenyao Mo72111912016-07-20 17:45:56 -070072 if (var.isArray())
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080073 {
Zhenyao Mod7490962016-11-09 15:49:51 -080074 // Assign the array elements one by one to keep the AST compatible with ESSL 1.00 which
75 // doesn't have array assignment.
Zhenyao Mo72111912016-07-20 17:45:56 -070076 size_t pos = name.find_last_of('[');
77 if (pos != TString::npos)
Corentin Wallez509e4562016-08-25 14:55:44 -040078 {
Zhenyao Mo72111912016-07-20 17:45:56 -070079 name = name.substr(0, pos);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080080 }
Zhenyao Mod7490962016-11-09 15:49:51 -080081 TType elementType = sh::GetShaderVariableBasicType(var);
82 TType arrayType = elementType;
83 arrayType.setArraySize(var.elementCount());
Zhenyao Mof9312682016-07-22 12:51:31 -070084
Kai Ninomiyad1bed172017-04-12 17:35:54 -070085 // Workaround for http://crbug.com/709317
86 // This loop is reversed to initialize elements in increasing
87 // order [0 1 2 ...]. Otherwise, they're initialized in
88 // decreasing order [... 2 1 0], due to
89 // `sequence->insert(sequence->begin(), ...)` below.
90 for (unsigned int i = var.arraySize; i > 0; --i)
Corentin Wallez509e4562016-08-25 14:55:44 -040091 {
Kai Ninomiyad1bed172017-04-12 17:35:54 -070092 unsigned int index = i - 1;
Zhenyao Mod7490962016-11-09 15:49:51 -080093 TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, arrayType);
Olli Etuaho3272a6d2016-08-29 17:54:50 +030094 TIntermBinary *element = new TIntermBinary(EOpIndexDirect, arraySymbol,
Kai Ninomiyad1bed172017-04-12 17:35:54 -070095 TIntermTyped::CreateIndexNode(index));
Zhenyao Mof9312682016-07-22 12:51:31 -070096
Corentin Wallez509e4562016-08-25 14:55:44 -040097 TIntermTyped *zero = TIntermTyped::CreateZero(elementType);
98 TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero);
99
100 sequence->insert(sequence->begin(), assignment);
Zhenyao Mof9312682016-07-22 12:51:31 -0700101 }
102 }
Zhenyao Mod7490962016-11-09 15:49:51 -0800103 else if (var.isStruct())
104 {
105 TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
106 ASSERT(structInfo);
107
108 TIntermSymbol *symbol = new TIntermSymbol(0, name, structInfo->getType());
109 TIntermTyped *zero = TIntermTyped::CreateZero(structInfo->getType());
110
111 TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
112 sequence->insert(sequence->begin(), assign);
113 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800114 else
115 {
Zhenyao Mod7490962016-11-09 15:49:51 -0800116 TType type = sh::GetShaderVariableBasicType(var);
Zhenyao Mo72111912016-07-20 17:45:56 -0700117 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Corentin Wallez509e4562016-08-25 14:55:44 -0400118 TIntermTyped *zero = TIntermTyped::CreateZero(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800119
Corentin Wallez509e4562016-08-25 14:55:44 -0400120 TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
121 sequence->insert(sequence->begin(), assign);
122 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800123 }
124}
125
Zhenyao Mo72111912016-07-20 17:45:56 -0700126} // namespace anonymous
127
Zhenyao Mod7490962016-11-09 15:49:51 -0800128void InitializeVariables(TIntermNode *root,
129 const InitVariableList &vars,
130 const TSymbolTable &symbolTable)
Zhenyao Mo72111912016-07-20 17:45:56 -0700131{
Zhenyao Mod7490962016-11-09 15:49:51 -0800132 VariableInitializer initializer(vars, symbolTable);
Zhenyao Mo72111912016-07-20 17:45:56 -0700133 root->traverse(&initializer);
134}
Jamie Madill45bcc782016-11-07 13:58:48 -0500135
136} // namespace sh