Hash :
e53c98ba
Author :
Date :
2014-02-03T11:57:13
Add work-around for D3D9 shader compiler bug. With certain selection statements with a vertex input in the condition and side-effects in the else-block, we'd run in to a D3D9 compiler bug which would cause incorrect results. We can work around this bug in D3D9 by selectively rewriting these statements to use an 'else if' clause instead of 'else'. BUG=322794 Change-Id: I93c96fb201ff4959c00d9a36321faac7e0343278 Reviewed-on: https://chromium-review.googlesource.com/184681 Reviewed-by: Nicolas Capens <nicolascapens@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RewriteElseBlocks.cpp: Implementation for tree transform to change
// all if-else blocks to if-if blocks.
//
#include "compiler/translator/RewriteElseBlocks.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type)
{
TType variableType(type, EbpHigh, EvqInternal);
return new TIntermSymbol(-1, name, variableType);
}
TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType)
{
TIntermBinary *binary = new TIntermBinary(op);
binary->setLeft(left);
binary->setRight(right);
binary->setType(resultType);
return binary;
}
TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
{
TIntermUnary *unary = new TIntermUnary(op, operand->getType());
unary->setOperand(operand);
return unary;
}
bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
{
switch (node->getOp())
{
case EOpSequence:
{
for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
{
TIntermNode *statement = node->getSequence()[statementIndex];
TIntermSelection *selection = statement->getAsSelectionNode();
if (selection && selection->getFalseBlock() != NULL)
{
node->getSequence()[statementIndex] = rewriteSelection(selection);
delete selection;
}
}
}
break;
default: break;
}
return true;
}
TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
{
ASSERT(selection->getFalseBlock() != NULL);
TString temporaryName = "cond_" + str(mTemporaryIndex++);
TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
TType resultType(EbtBool, EbpUndefined);
TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
typedCondition, resultType);
TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
selection->getFalseBlock(), NULL);
TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
selection->getTrueBlock(), falseBlock);
TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
declaration->getSequence().push_back(storeCondition);
TIntermAggregate *block = new TIntermAggregate(EOpSequence);
block->getSequence().push_back(declaration);
block->getSequence().push_back(newIfElse);
return block;
}
void RewriteElseBlocks(TIntermNode *node)
{
ElseBlockRewriter rewriter;
node->traverse(&rewriter);
}
}