Bug 1355321 - Part1: Revert "Bug 1347866 - Part2: Revert "translator: remove code related to for-loop unrolling""; r=jgilbert

This reverts commit 21a87c994f849488d7d6a143b93de9892e04f435.

MozReview-Commit-ID: 8QKjAHW0vhq

--HG--
extra : rebase_source : 416f2072b2414d91e6924f3b608c5f92a1a24029
This commit is contained in:
Chih-Yi Leu 2017-04-13 18:11:44 +08:00
Родитель 0257b6738b
Коммит e3eeba7caf
17 изменённых файлов: 64 добавлений и 711 удалений

Просмотреть файл

@ -75,12 +75,29 @@ const ShCompileOptions SH_OBJECT_CODE = UINT64_C(1) << 2;
const ShCompileOptions SH_VARIABLES = UINT64_C(1) << 3;
const ShCompileOptions SH_LINE_DIRECTIVES = UINT64_C(1) << 4;
const ShCompileOptions SH_SOURCE_PATH = UINT64_C(1) << 5;
const ShCompileOptions SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = UINT64_C(1) << 6;
// If a sampler array index happens to be a loop index,
// 1) if its type is integer, unroll the loop.
// 2) if its type is float, fail the shader compile.
// This is to work around a mac driver bug.
const ShCompileOptions SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = UINT64_C(1) << 7;
// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 on AMD.
// From GLSL >= 4.20, it's optional to add invariant for fragment input, but GPU vendors have
// different implementations about this. Some drivers forbid invariant in fragment for GLSL>= 4.20,
// e.g. Linux Mesa, some drivers treat that as optional, e.g. NVIDIA, some drivers require invariant
// must match between vertex and fragment shader, e.g. AMD. The behavior on AMD is obviously wrong.
// Remove invariant for input in fragment shader to workaround the restriction on Intel Mesa.
// But don't remove on AMD Linux to avoid triggering the bug on AMD.
const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 6;
// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
// AMD driver in Linux requires invariant qualifier to match between vertex and fragment shaders,
// while ESSL3 disallows invariant qualifier in fragment shader and GLSL >= 4.2 doesn't require
// invariant qualifier to match between shaders. Remove invariant qualifier from vertex shader to
// workaround AMD driver bug.
// Note that the two flags take effect on ESSL3 input shaders translated to GLSL 4.1 or lower and to
// GLSL 4.2 or newer on Linux AMD.
// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
// developers' content. A more complex workaround of dynamically generating, compiling, and
// re-linking shaders that use these qualifiers should be implemented.
const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 7;
// This flag works around bug in Intel Mac drivers related to abs(i) where
// i is an integer.
@ -186,29 +203,6 @@ const ShCompileOptions SH_EMULATE_ISNAN_FLOAT_FUNCTION = UINT64_C(1) << 27;
// layout qualifier to be considered active. The uniform block itself is also considered active.
const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28;
// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 on AMD.
// From GLSL >= 4.20, it's optional to add invariant for fragment input, but GPU vendors have
// different implementations about this. Some drivers forbid invariant in fragment for GLSL>= 4.20,
// e.g. Linux Mesa, some drivers treat that as optional, e.g. NVIDIA, some drivers require invariant
// must match between vertex and fragment shader, e.g. AMD. The behavior on AMD is obviously wrong.
// Remove invariant for input in fragment shader to workaround the restriction on Intel Mesa.
// But don't remove on AMD Linux to avoid triggering the bug on AMD.
const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 29;
// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
// AMD driver in Linux requires invariant qualifier to match between vertex and fragment shaders,
// while ESSL3 disallows invariant qualifier in fragment shader and GLSL >= 4.2 doesn't require
// invariant qualifier to match between shaders. Remove invariant qualifier from vertex shader to
// workaround AMD driver bug.
// Note that the two flags take effect on ESSL3 input shaders translated to GLSL 4.1 or lower and to
// GLSL 4.2 or newer on Linux AMD.
// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
// developers' content. A more complex workaround of dynamically generating, compiling, and
// re-linking shaders that use these qualifiers should be implemented.
const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 30;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy
{

Просмотреть файл

@ -50,7 +50,6 @@ UNIFIED_SOURCES += [
'src/compiler/translator/ExpandIntegerPowExpressions.cpp',
'src/compiler/translator/ExtensionGLSL.cpp',
'src/compiler/translator/FlagStd140Structs.cpp',
'src/compiler/translator/ForLoopUnroll.cpp',
'src/compiler/translator/InfoSink.cpp',
'src/compiler/translator/Initialize.cpp',
'src/compiler/translator/InitializeDll.cpp',
@ -61,7 +60,6 @@ UNIFIED_SOURCES += [
'src/compiler/translator/IntermNodePatternMatcher.cpp',
'src/compiler/translator/intermOut.cpp',
'src/compiler/translator/IntermTraverse.cpp',
'src/compiler/translator/LoopInfo.cpp',
'src/compiler/translator/Operator.cpp',
'src/compiler/translator/OutputESSL.cpp',
'src/compiler/translator/OutputGLSL.cpp',

Просмотреть файл

@ -1,14 +1,3 @@
//
// 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.
//
// commit.h:
// This is a default commit hash header, when git is not available.
//
#define ANGLE_COMMIT_HASH "unknown hash"
#define ANGLE_COMMIT_HASH "dec065540d5f"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "unknown date"
#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD
#define ANGLE_COMMIT_DATE "2017-04-10 16:10:11 +0800"

Просмотреть файл

@ -54,8 +54,6 @@
'compiler/translator/ExtensionBehavior.h',
'compiler/translator/FlagStd140Structs.cpp',
'compiler/translator/FlagStd140Structs.h',
'compiler/translator/ForLoopUnroll.cpp',
'compiler/translator/ForLoopUnroll.h',
'compiler/translator/HashNames.h',
'compiler/translator/InfoSink.cpp',
'compiler/translator/InfoSink.h',
@ -73,9 +71,6 @@
'compiler/translator/IntermTraverse.cpp',
'compiler/translator/Intermediate.h',
'compiler/translator/Intermediate.cpp',
'compiler/translator/LoopInfo.cpp',
'compiler/translator/LoopInfo.h',
'compiler/translator/MMap.h',
'compiler/translator/NodeSearch.h',
'compiler/translator/Operator.cpp',
'compiler/translator/Operator.h',

Просмотреть файл

@ -16,7 +16,6 @@
#include "compiler/translator/DeferGlobalInitializers.h"
#include "compiler/translator/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ForLoopUnroll.h"
#include "compiler/translator/Initialize.h"
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h"
@ -370,26 +369,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
}
}
// Unroll for-loop markup needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
{
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex,
shouldRunLoopAndIndexingValidation(compileOptions));
root->traverse(&marker);
}
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX))
{
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex,
shouldRunLoopAndIndexingValidation(compileOptions));
root->traverse(&marker);
if (marker.samplerArrayIndexIsFloatLoopIndex())
{
infoSink.info.prefix(EPrefixError);
infoSink.info << "sampler array index is float loop index";
success = false;
}
}
// Built-in function emulation needs to happen after validateLimitations pass.
if (success)
{
@ -506,17 +485,6 @@ bool TCompiler::compile(const char *const shaderStrings[],
compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
}
ShCompileOptions unrollFlags =
SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX | SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0 &&
(compileOptions & unrollFlags) != 0)
{
infoSink.info.prefix(EPrefixError);
infoSink.info
<< "Unsupported compile flag combination: unroll & ADD_TRUE_TO_LOOP_CONDITION";
return false;
}
TScopedPoolAllocator scopedAlloc(&allocator);
TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);

Просмотреть файл

@ -1,102 +0,0 @@
//
// Copyright (c) 2002-2013 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.
//
#include "compiler/translator/ForLoopUnroll.h"
#include "compiler/translator/ValidateLimitations.h"
#include "angle_gl.h"
namespace sh
{
bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
{
if (mUnrollCondition != kSamplerArrayIndex)
return true;
// If a sampler array index is also the loop index,
// 1) if the index type is integer, mark the loop for unrolling;
// 2) if the index type if float, set a flag to later fail compile.
switch (node->getOp())
{
case EOpIndexIndirect:
if (node->getLeft() != NULL && node->getRight() != NULL && node->getLeft()->getAsSymbolNode())
{
TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode();
if (IsSampler(symbol->getBasicType()) && symbol->isArray() && !mLoopStack.empty())
{
mVisitSamplerArrayIndexNodeInsideLoop = true;
node->getRight()->traverse(this);
mVisitSamplerArrayIndexNodeInsideLoop = false;
// We have already visited all the children.
return false;
}
}
break;
default:
break;
}
return true;
}
bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
{
bool canBeUnrolled = mHasRunLoopValidation;
if (!mHasRunLoopValidation)
{
canBeUnrolled = ValidateLimitations::IsLimitedForLoop(node);
}
if (mUnrollCondition == kIntegerIndex && canBeUnrolled)
{
// Check if loop index type is integer.
// This is called after ValidateLimitations pass, so the loop has the limited form specified
// in ESSL 1.00 appendix A.
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
if (symbol->getBasicType() == EbtInt)
node->setUnrollFlag(true);
}
TIntermNode *body = node->getBody();
if (body != nullptr)
{
if (canBeUnrolled)
{
mLoopStack.push(node);
body->traverse(this);
mLoopStack.pop();
}
else
{
body->traverse(this);
}
}
// The loop is fully processed - no need to visit children.
return false;
}
void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol)
{
if (!mVisitSamplerArrayIndexNodeInsideLoop)
return;
TIntermLoop *loop = mLoopStack.findLoop(symbol);
if (loop)
{
switch (symbol->getBasicType())
{
case EbtFloat:
mSamplerArrayIndexIsFloatLoopIndex = true;
break;
case EbtInt:
loop->setUnrollFlag(true);
break;
default:
UNREACHABLE();
}
}
}
} // namespace sh

Просмотреть файл

@ -1,58 +0,0 @@
//
// Copyright (c) 2011 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.
//
#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
#include "compiler/translator/LoopInfo.h"
namespace sh
{
// This class detects for-loops that needs to be unrolled.
// Currently we support two unroll conditions:
// 1) kForLoopWithIntegerIndex: unroll if the index type is integer.
// 2) kForLoopWithSamplerArrayIndex: unroll where a sampler array index
// is also the loop integer index, and reject and fail a compile
// where a sampler array index is also the loop float index.
class ForLoopUnrollMarker : public TIntermTraverser
{
public:
enum UnrollCondition
{
kIntegerIndex,
kSamplerArrayIndex
};
ForLoopUnrollMarker(UnrollCondition condition, bool hasRunLoopValidation)
: TIntermTraverser(true, false, false),
mUnrollCondition(condition),
mSamplerArrayIndexIsFloatLoopIndex(false),
mVisitSamplerArrayIndexNodeInsideLoop(false),
mHasRunLoopValidation(hasRunLoopValidation)
{
}
bool visitBinary(Visit, TIntermBinary *node) override;
bool visitLoop(Visit, TIntermLoop *node) override;
void visitSymbol(TIntermSymbol *node) override;
bool samplerArrayIndexIsFloatLoopIndex() const
{
return mSamplerArrayIndexIsFloatLoopIndex;
}
private:
UnrollCondition mUnrollCondition;
TLoopStack mLoopStack;
bool mSamplerArrayIndexIsFloatLoopIndex;
bool mVisitSamplerArrayIndexNodeInsideLoop;
bool mHasRunLoopValidation;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_

Просмотреть файл

@ -201,7 +201,7 @@ class TIntermLoop : public TIntermNode
TIntermTyped *cond,
TIntermTyped *expr,
TIntermBlock *body)
: mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body), mUnrollFlag(false)
: mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
{
}
@ -219,17 +219,12 @@ class TIntermLoop : public TIntermNode
void setExpression(TIntermTyped *expression) { mExpr = expression; }
void setBody(TIntermBlock *body) { mBody = body; }
void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
bool getUnrollFlag() const { return mUnrollFlag; }
protected:
TLoopType mType;
TIntermNode *mInit; // for-loop initialization
TIntermTyped *mCond; // loop exit condition
TIntermTyped *mExpr; // for-loop expression
TIntermBlock *mBody; // loop body
bool mUnrollFlag; // Whether the loop should be unrolled or not.
};
//

Просмотреть файл

@ -1,214 +0,0 @@
//
// Copyright (c) 2002-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.
//
#include "compiler/translator/LoopInfo.h"
namespace sh
{
namespace
{
int EvaluateIntConstant(TIntermConstantUnion *node)
{
ASSERT(node && node->getUnionArrayPointer());
return node->getIConst(0);
}
int GetLoopIntIncrement(TIntermLoop *node)
{
TIntermNode *expr = node->getExpression();
// for expression has one of the following forms:
// loop_index++
// loop_index--
// loop_index += constant_expression
// loop_index -= constant_expression
// ++loop_index
// --loop_index
// The last two forms are not specified in the spec, but I am assuming
// its an oversight.
TIntermUnary *unOp = expr->getAsUnaryNode();
TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode();
TOperator op = EOpNull;
TIntermConstantUnion *incrementNode = NULL;
if (unOp)
{
op = unOp->getOp();
}
else if (binOp)
{
op = binOp->getOp();
ASSERT(binOp->getRight());
incrementNode = binOp->getRight()->getAsConstantUnion();
ASSERT(incrementNode);
}
int increment = 0;
// The operator is one of: ++ -- += -=.
switch (op)
{
case EOpPostIncrement:
case EOpPreIncrement:
ASSERT(unOp && !binOp);
increment = 1;
break;
case EOpPostDecrement:
case EOpPreDecrement:
ASSERT(unOp && !binOp);
increment = -1;
break;
case EOpAddAssign:
ASSERT(!unOp && binOp);
increment = EvaluateIntConstant(incrementNode);
break;
case EOpSubAssign:
ASSERT(!unOp && binOp);
increment = - EvaluateIntConstant(incrementNode);
break;
default:
UNREACHABLE();
}
return increment;
}
} // namespace anonymous
TLoopIndexInfo::TLoopIndexInfo()
: mId(-1),
mType(EbtVoid),
mInitValue(0),
mStopValue(0),
mIncrementValue(0),
mOp(EOpNull),
mCurrentValue(0)
{
}
void TLoopIndexInfo::fillInfo(TIntermLoop *node)
{
if (node == NULL)
return;
// Here we assume all the operations are valid, because the loop node is
// already validated in ValidateLimitations.
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
mId = symbol->getId();
mType = symbol->getBasicType();
if (mType == EbtInt)
{
TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
mInitValue = EvaluateIntConstant(initNode);
mCurrentValue = mInitValue;
mIncrementValue = GetLoopIntIncrement(node);
TIntermBinary* binOp = node->getCondition()->getAsBinaryNode();
mStopValue = EvaluateIntConstant(
binOp->getRight()->getAsConstantUnion());
mOp = binOp->getOp();
}
}
bool TLoopIndexInfo::satisfiesLoopCondition() const
{
// Relational operator is one of: > >= < <= == or !=.
switch (mOp)
{
case EOpEqual:
return (mCurrentValue == mStopValue);
case EOpNotEqual:
return (mCurrentValue != mStopValue);
case EOpLessThan:
return (mCurrentValue < mStopValue);
case EOpGreaterThan:
return (mCurrentValue > mStopValue);
case EOpLessThanEqual:
return (mCurrentValue <= mStopValue);
case EOpGreaterThanEqual:
return (mCurrentValue >= mStopValue);
default:
UNREACHABLE();
return false;
}
}
TLoopInfo::TLoopInfo()
: loop(NULL)
{
}
TLoopInfo::TLoopInfo(TIntermLoop *node)
: loop(node)
{
index.fillInfo(node);
}
TIntermLoop *TLoopStack::findLoop(TIntermSymbol *symbol)
{
if (!symbol)
return NULL;
for (iterator iter = begin(); iter != end(); ++iter)
{
if (iter->index.getId() == symbol->getId())
return iter->loop;
}
return NULL;
}
TLoopIndexInfo *TLoopStack::getIndexInfo(TIntermSymbol *symbol)
{
if (!symbol)
return NULL;
for (iterator iter = begin(); iter != end(); ++iter)
{
if (iter->index.getId() == symbol->getId())
return &(iter->index);
}
return NULL;
}
void TLoopStack::step()
{
ASSERT(!empty());
rbegin()->index.step();
}
bool TLoopStack::satisfiesLoopCondition()
{
ASSERT(!empty());
return rbegin()->index.satisfiesLoopCondition();
}
bool TLoopStack::needsToReplaceSymbolWithValue(TIntermSymbol *symbol)
{
TIntermLoop *loop = findLoop(symbol);
return loop && loop->getUnrollFlag();
}
int TLoopStack::getLoopIndexValue(TIntermSymbol *symbol)
{
TLoopIndexInfo *info = getIndexInfo(symbol);
ASSERT(info);
return info->getCurrentValue();
}
void TLoopStack::push(TIntermLoop *loop)
{
TLoopInfo info(loop);
push_back(info);
}
void TLoopStack::pop()
{
pop_back();
}
} // namespace sh

Просмотреть файл

@ -1,85 +0,0 @@
//
// Copyright (c) 2002-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.
//
#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_
#define COMPILER_TRANSLATOR_LOOPINFO_H_
#include "compiler/translator/IntermNode.h"
namespace sh
{
class TLoopIndexInfo
{
public:
TLoopIndexInfo();
// If type is EbtInt, fill all fields of the structure with info
// extracted from a loop node.
// If type is not EbtInt, only fill id and type.
void fillInfo(TIntermLoop *node);
int getId() const { return mId; }
void setId(int id) { mId = id; }
TBasicType getType() const { return mType; }
void setType(TBasicType type) { mType = type; }
int getCurrentValue() const { return mCurrentValue; }
void step() { mCurrentValue += mIncrementValue; }
// Check if the current value satisfies the loop condition.
bool satisfiesLoopCondition() const;
private:
int mId;
TBasicType mType; // Either EbtInt or EbtFloat
// Below fields are only valid if the index's type is int.
int mInitValue;
int mStopValue;
int mIncrementValue;
TOperator mOp;
int mCurrentValue;
};
struct TLoopInfo
{
TLoopIndexInfo index;
TIntermLoop *loop;
TLoopInfo();
TLoopInfo(TIntermLoop *node);
};
class TLoopStack : public TVector<TLoopInfo>
{
public:
// Search loop stack for a loop whose index matches the input symbol.
TIntermLoop *findLoop(TIntermSymbol *symbol);
// Find the loop index info in the loop stack by the input symbol.
TLoopIndexInfo *getIndexInfo(TIntermSymbol *symbol);
// Update the currentValue for the next loop iteration.
void step();
// Return false if loop condition is no longer satisfied.
bool satisfiesLoopCondition();
// Check if the symbol is the index of a loop that's unrolled.
bool needsToReplaceSymbolWithValue(TIntermSymbol *symbol);
// Return the current value of a given loop index symbol.
int getLoopIndexValue(TIntermSymbol *symbol);
void push(TIntermLoop *info);
void pop();
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_LOOPINFO_H_

Просмотреть файл

@ -1,56 +0,0 @@
//
// Copyright (c) 2002-2010 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.
//
#ifndef COMPILER_TRANSLATOR_MMAP_H_
#define COMPILER_TRANSLATOR_MMAP_H_
//
// Encapsulate memory mapped files
//
class TMMap {
public:
TMMap(const char* fileName) :
fSize(-1), // -1 is the error value returned by GetFileSize()
fp(NULL),
fBuff(0) // 0 is the error value returned by MapViewOfFile()
{
if ((fp = fopen(fileName, "r")) == NULL)
return;
char c = getc(fp);
fSize = 0;
while (c != EOF) {
fSize++;
c = getc(fp);
}
if (c == EOF)
fSize++;
rewind(fp);
fBuff = (char*)malloc(sizeof(char) * fSize);
int count = 0;
c = getc(fp);
while (c != EOF) {
fBuff[count++] = c;
c = getc(fp);
}
fBuff[count++] = c;
}
char* getData() { return fBuff; }
int getSize() { return fSize; }
~TMMap() {
if (fp != NULL)
fclose(fp);
}
private:
int fSize; // size of file to map in
FILE *fp;
char* fBuff; // the actual data;
};
#endif // COMPILER_TRANSLATOR_MMAP_H_

Просмотреть файл

@ -389,10 +389,7 @@ void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase &out = objSink();
if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node))
out << mLoopUnrollStack.getLoopIndexValue(node);
else
out << hashVariableName(node->getName());
out << hashVariableName(node->getName());
if (mDeclaringVariables && node->getType().isArray())
out << arrayBrackets(node->getType());
@ -1137,49 +1134,22 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
TLoopType loopType = node->getType();
// Only for loops can be unrolled
ASSERT(!node->getUnrollFlag() || loopType == ELoopFor);
if (loopType == ELoopFor) // for loop
{
if (!node->getUnrollFlag())
{
out << "for (";
if (node->getInit())
node->getInit()->traverse(this);
out << "; ";
out << "for (";
if (node->getInit())
node->getInit()->traverse(this);
out << "; ";
if (node->getCondition())
node->getCondition()->traverse(this);
out << "; ";
if (node->getCondition())
node->getCondition()->traverse(this);
out << "; ";
if (node->getExpression())
node->getExpression()->traverse(this);
out << ")\n";
if (node->getExpression())
node->getExpression()->traverse(this);
out << ")\n";
visitCodeBlock(node->getBody());
}
else
{
// Need to put a one-iteration loop here to handle break.
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSymbol *indexSymbol =
(*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
TString name = hashVariableName(indexSymbol->getName());
out << "for (int " << name << " = 0; "
<< name << " < 1; "
<< "++" << name << ")\n";
out << "{\n";
mLoopUnrollStack.push(node);
while (mLoopUnrollStack.satisfiesLoopCondition())
{
visitCodeBlock(node->getBody());
mLoopUnrollStack.step();
}
mLoopUnrollStack.pop();
out << "}\n";
}
visitCodeBlock(node->getBody());
}
else if (loopType == ELoopWhile) // while loop
{

Просмотреть файл

@ -10,7 +10,6 @@
#include <set>
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/LoopInfo.h"
#include "compiler/translator/ParseContext.h"
namespace sh
@ -92,9 +91,6 @@ class TOutputGLSLBase : public TIntermTraverser
// This set contains all the ids of the structs from every scope.
std::set<int> mDeclaredStructs;
// Stack of loops that need to be unrolled.
TLoopStack mLoopUnrollStack;
ShArrayIndexClampingStrategy mClampingStrategy;
// name hashing.

Просмотреть файл

@ -16,6 +16,17 @@ namespace sh
namespace
{
int GetLoopSymbolId(TIntermLoop *loop)
{
// Here we assume all the operations are valid, because the loop node is
// already validated before this call.
TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence();
TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
return symbol->getId();
}
// Traverses a node to check if it represents a constant index expression.
// Definition:
// constant-index-expressions are a superset of constant-expressions.
@ -28,10 +39,8 @@ namespace
class ValidateConstIndexExpr : public TIntermTraverser
{
public:
ValidateConstIndexExpr(TLoopStack& stack)
: TIntermTraverser(true, false, false),
mValid(true),
mLoopStack(stack)
ValidateConstIndexExpr(const std::vector<int> &loopSymbols)
: TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols)
{
}
@ -44,14 +53,15 @@ class ValidateConstIndexExpr : public TIntermTraverser
// constant index expression.
if (mValid)
{
mValid = (symbol->getQualifier() == EvqConst) ||
(mLoopStack.findLoop(symbol));
bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(),
symbol->getId()) != mLoopSymbolIds.end();
mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol;
}
}
private:
bool mValid;
TLoopStack& mLoopStack;
const std::vector<int> mLoopSymbolIds;
};
} // namespace anonymous
@ -80,9 +90,9 @@ bool ValidateLimitations::IsLimitedForLoop(TIntermLoop *loop)
TIntermNode *body = loop->getBody();
if (body != nullptr)
{
validate.mLoopStack.push(loop);
validate.mLoopSymbolIds.push_back(GetLoopSymbolId(loop));
body->traverse(&validate);
validate.mLoopStack.pop();
validate.mLoopSymbolIds.pop_back();
}
return (validate.mNumErrors == 0);
}
@ -140,9 +150,9 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
TIntermNode *body = node->getBody();
if (body != NULL)
{
mLoopStack.push(node);
mLoopSymbolIds.push_back(GetLoopSymbolId(node));
body->traverse(this);
mLoopStack.pop();
mLoopSymbolIds.pop_back();
}
// The loop is fully processed - no need to visit children.
@ -163,12 +173,13 @@ void ValidateLimitations::error(TSourceLoc loc,
bool ValidateLimitations::withinLoopBody() const
{
return !mLoopStack.empty();
return !mLoopSymbolIds.empty();
}
bool ValidateLimitations::isLoopIndex(TIntermSymbol *symbol)
{
return mLoopStack.findLoop(symbol) != NULL;
return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) !=
mLoopSymbolIds.end();
}
bool ValidateLimitations::validateLoopType(TIntermLoop *node)
@ -474,7 +485,7 @@ bool ValidateLimitations::isConstIndexExpr(TIntermNode *node)
{
ASSERT(node != NULL);
ValidateConstIndexExpr validate(mLoopStack);
ValidateConstIndexExpr validate(mLoopSymbolIds);
node->traverse(&validate);
return validate.isValid();
}

Просмотреть файл

@ -8,7 +8,6 @@
#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/LoopInfo.h"
namespace sh
{
@ -58,7 +57,7 @@ class ValidateLimitations : public TIntermTraverser
sh::GLenum mShaderType;
TInfoSinkBase *mSink;
int mNumErrors;
TLoopStack mLoopStack;
std::vector<int> mLoopSymbolIds;
bool mValidateIndexing;
bool mValidateInnerLoops;
};

Просмотреть файл

@ -51,7 +51,6 @@ UNIFIED_SOURCES += [
'../compiler/translator/ExpandIntegerPowExpressions.cpp',
'../compiler/translator/ExtensionGLSL.cpp',
'../compiler/translator/FlagStd140Structs.cpp',
'../compiler/translator/ForLoopUnroll.cpp',
'../compiler/translator/InfoSink.cpp',
'../compiler/translator/Initialize.cpp',
'../compiler/translator/InitializeDll.cpp',
@ -62,7 +61,6 @@ UNIFIED_SOURCES += [
'../compiler/translator/IntermNodePatternMatcher.cpp',
'../compiler/translator/intermOut.cpp',
'../compiler/translator/IntermTraverse.cpp',
'../compiler/translator/LoopInfo.cpp',
'../compiler/translator/Operator.cpp',
'../compiler/translator/OutputESSL.cpp',
'../compiler/translator/OutputGLSL.cpp',

Просмотреть файл

@ -149,12 +149,6 @@ class MalformedComputeShaderTest : public MalformedShaderTest
}
};
class UnrollForLoopsTest : public MalformedShaderTest
{
public:
UnrollForLoopsTest() { mExtraCompileOptions = SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; }
};
// This is a test for a bug that used to exist in ANGLE:
// Calling a function with all parameters missing should not succeed.
TEST_F(MalformedShaderTest, FunctionParameterMismatch)
@ -1445,45 +1439,6 @@ TEST_F(MalformedWebGL1ShaderTest, NonConstantLoopIndex)
}
}
// Regression test for an old crash bug in ANGLE.
// ForLoopUnroll used to crash when it encountered a while loop.
TEST_F(UnrollForLoopsTest, WhileLoop)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" while (true) {\n"
" gl_FragColor = vec4(0.0);\n"
" break;\n"
" }\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Regression test for an old crash bug in ANGLE.
// ForLoopUnroll used to crash when it encountered a loop that didn't fit the ESSL 1.00
// Appendix A limitations.
TEST_F(UnrollForLoopsTest, UnlimitedForLoop)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" for (;true;) {\n"
" gl_FragColor = vec4(0.0);\n"
" break;\n"
" }\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Check that indices that are not integers are rejected.
// The check should be done even if ESSL 1.00 Appendix A limitations are not applied.
TEST_F(MalformedShaderTest, NonIntegerIndex)