Commit 72111915 by Zhenyao Mo Committed by Commit Bot

Initialize all output variables.

BUG=angleproject:1441 TEST=bots Change-Id: Ia4cf415d8346c3234bf0f548a178ee3ea8cd35c4 Reviewed-on: https://chromium-review.googlesource.com/362110Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Zhenyao Mo <zmo@chromium.org>
parent dacac90a
...@@ -48,7 +48,7 @@ typedef unsigned int GLenum; ...@@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 149 #define ANGLE_SH_VERSION 150
typedef enum { typedef enum {
SH_GLES2_SPEC, SH_GLES2_SPEC,
...@@ -184,10 +184,10 @@ typedef enum { ...@@ -184,10 +184,10 @@ typedef enum {
// independent of |a|'s value. // independent of |a|'s value.
SH_UNFOLD_SHORT_CIRCUIT = 0x10000, SH_UNFOLD_SHORT_CIRCUIT = 0x10000,
// This flag initializes varyings without static use in vertex shader // This flag initializes output variables to 0 at the beginning of main().
// at the beginning of main(), and has no effects in the fragment shader. // It is to avoid undefined behaviors.
// It is intended as a workaround for drivers which incorrectly optimize SH_INIT_OUTPUT_VARIABLES = 0x20000,
// out such varyings and cause a link failure. // TODO(zmo): obsolete, remove after ANGLE roll into Chromium.
SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000, SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000,
// This flag scalarizes vec/ivec/bvec/mat constructor args. // This flag scalarizes vec/ivec/bvec/mat constructor args.
......
...@@ -362,9 +362,10 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -362,9 +362,10 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
infoSink.info << "too many uniforms"; infoSink.info << "too many uniforms";
} }
} }
if (success && shaderType == GL_VERTEX_SHADER && if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES))
(compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE)) {
initializeVaryingsWithoutStaticUse(root); initializeOutputVariables(root, shaderType);
}
} }
if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
...@@ -810,37 +811,32 @@ bool TCompiler::enforcePackingRestrictions() ...@@ -810,37 +811,32 @@ bool TCompiler::enforcePackingRestrictions()
void TCompiler::initializeGLPosition(TIntermNode* root) void TCompiler::initializeGLPosition(TIntermNode* root)
{ {
InitializeVariables::InitVariableInfoList variables; InitVariableList list;
InitializeVariables::InitVariableInfo var( sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
"gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); var.name = "gl_Position";
variables.push_back(var); list.push_back(var);
InitializeVariables initializer(variables); InitializeVariables(root, list);
root->traverse(&initializer);
} }
void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) void TCompiler::initializeOutputVariables(TIntermNode *root, sh::GLenum shaderType)
{ {
InitializeVariables::InitVariableInfoList variables; InitVariableList list;
for (size_t ii = 0; ii < varyings.size(); ++ii) if (shaderType == GL_VERTEX_SHADER)
{ {
const sh::Varying& varying = varyings[ii]; for (auto var : varyings)
if (varying.staticUse)
continue;
unsigned char primarySize = static_cast<unsigned char>(gl::VariableColumnCount(varying.type));
unsigned char secondarySize = static_cast<unsigned char>(gl::VariableRowCount(varying.type));
TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray());
TString name = varying.name.c_str();
if (varying.isArray())
{ {
type.setArraySize(varying.arraySize); sh::ExpandVariable(var, var.name, var.mappedName, false, &list);
name = name.substr(0, name.find_first_of('[')); }
}
else
{
ASSERT(shaderType == GL_FRAGMENT_SHADER);
for (auto var : outputVariables)
{
list.push_back(var);
} }
InitializeVariables::InitVariableInfo var(name, type);
variables.push_back(var);
} }
InitializeVariables initializer(variables); InitializeVariables(root, list);
root->traverse(&initializer);
} }
const TExtensionBehavior& TCompiler::getExtensionBehavior() const const TExtensionBehavior& TCompiler::getExtensionBehavior() const
......
...@@ -130,11 +130,9 @@ class TCompiler : public TShHandleBase ...@@ -130,11 +130,9 @@ class TCompiler : public TShHandleBase
// Returns true if, after applying the packing rules in the GLSL 1.017 spec // Returns true if, after applying the packing rules in the GLSL 1.017 spec
// Appendix A, section 7, the shader does not use too many uniforms. // Appendix A, section 7, the shader does not use too many uniforms.
bool enforcePackingRestrictions(); bool enforcePackingRestrictions();
// Insert statements to initialize varyings without static use in the beginning // Insert statements to initialize output variables in the beginning of main().
// of main(). It is to work around a Mac driver where such varyings in a vertex // This is to avoid undefined behaviors.
// shader may be optimized out incorrectly at compile time, causing a link failure. void initializeOutputVariables(TIntermNode *root, sh::GLenum shaderType);
// This function should only be applied to vertex shaders.
void initializeVaryingsWithoutStaticUse(TIntermNode* root);
// Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). // Insert gl_Position = vec4(0,0,0,0) to the beginning of main().
// It is to work around a Linux driver bug where missing this causes compile failure // It is to work around a Linux driver bug where missing this causes compile failure
// while spec says it is allowed. // while spec says it is allowed.
......
...@@ -6,23 +6,40 @@ ...@@ -6,23 +6,40 @@
#include "compiler/translator/InitializeVariables.h" #include "compiler/translator/InitializeVariables.h"
#include "angle_gl.h"
#include "common/debug.h" #include "common/debug.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/util.h"
namespace namespace
{ {
TIntermConstantUnion *constructFloatConstUnionNode(const TType &type) TIntermConstantUnion *constructConstUnionNode(const TType &type)
{ {
TType myType = type; TType myType = type;
unsigned char size = static_cast<unsigned char>(myType.getNominalSize()); myType.clearArrayness();
if (myType.isMatrix()) myType.setQualifier(EvqConst);
size *= size; size_t size = myType.getObjectSize();
TConstantUnion *u = new TConstantUnion[size]; TConstantUnion *u = new TConstantUnion[size];
for (int ii = 0; ii < size; ++ii) for (size_t ii = 0; ii < size; ++ii)
{
switch (type.getBasicType())
{
case EbtFloat:
u[ii].setFConst(0.0f); u[ii].setFConst(0.0f);
break;
case EbtInt:
u[ii].setIConst(0);
break;
case EbtUInt:
u[ii].setUConst(0u);
break;
default:
UNREACHABLE();
return nullptr;
}
}
myType.clearArrayness();
myType.setQualifier(EvqConst);
TIntermConstantUnion *node = new TIntermConstantUnion(u, myType); TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
return node; return node;
} }
...@@ -37,9 +54,33 @@ TIntermConstantUnion *constructIndexNode(int index) ...@@ -37,9 +54,33 @@ TIntermConstantUnion *constructIndexNode(int index)
return node; return node;
} }
} // namespace anonymous class VariableInitializer : public TIntermTraverser
{
public:
VariableInitializer(const InitVariableList &vars)
: TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false)
{
}
protected:
bool visitBinary(Visit, TIntermBinary *node) override { return false; }
bool visitUnary(Visit, TIntermUnary *node) override { return false; }
bool visitSelection(Visit, TIntermSelection *node) override { return false; }
bool visitLoop(Visit, TIntermLoop *node) override { return false; }
bool visitBranch(Visit, TIntermBranch *node) override { return false; }
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private:
void insertInitCode(TIntermSequence *sequence);
const InitVariableList &mVariables;
bool mCodeInserted;
};
bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node) // VariableInitializer implementation.
bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
bool visitChildren = !mCodeInserted; bool visitChildren = !mCodeInserted;
switch (node->getOp()) switch (node->getOp())
...@@ -77,28 +118,33 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -77,28 +118,33 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node)
return visitChildren; return visitChildren;
} }
void InitializeVariables::insertInitCode(TIntermSequence *sequence) void VariableInitializer::insertInitCode(TIntermSequence *sequence)
{ {
for (size_t ii = 0; ii < mVariables.size(); ++ii) for (size_t ii = 0; ii < mVariables.size(); ++ii)
{ {
const InitVariableInfo &varInfo = mVariables[ii]; const sh::ShaderVariable &var = mVariables[ii];
ASSERT(!var.isStruct());
if (varInfo.type.isArray()) TType type = sh::ConvertShaderVariableTypeToTType(var.type);
TString name = TString(var.name.c_str());
if (var.isArray())
{ {
for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) size_t pos = name.find_last_of('[');
if (pos != TString::npos)
name = name.substr(0, pos);
for (int index = static_cast<int>(var.arraySize) - 1; index >= 0; --index)
{ {
TIntermBinary *assign = new TIntermBinary(EOpAssign); TIntermBinary *assign = new TIntermBinary(EOpAssign);
sequence->insert(sequence->begin(), assign); sequence->insert(sequence->begin(), assign);
TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
indexDirect->setLeft(symbol); indexDirect->setLeft(symbol);
TIntermConstantUnion *indexNode = constructIndexNode(index); TIntermConstantUnion *indexNode = constructIndexNode(index);
indexDirect->setRight(indexNode); indexDirect->setRight(indexNode);
assign->setLeft(indexDirect); assign->setLeft(indexDirect);
TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
assign->setRight(zeroConst); assign->setRight(zeroConst);
} }
} }
...@@ -106,12 +152,19 @@ void InitializeVariables::insertInitCode(TIntermSequence *sequence) ...@@ -106,12 +152,19 @@ void InitializeVariables::insertInitCode(TIntermSequence *sequence)
{ {
TIntermBinary *assign = new TIntermBinary(EOpAssign); TIntermBinary *assign = new TIntermBinary(EOpAssign);
sequence->insert(sequence->begin(), assign); sequence->insert(sequence->begin(), assign);
TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
assign->setLeft(symbol); assign->setLeft(symbol);
TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
assign->setRight(zeroConst); assign->setRight(zeroConst);
} }
} }
} }
} // namespace anonymous
void InitializeVariables(TIntermNode *root, const InitVariableList &vars)
{
VariableInitializer initializer(vars);
root->traverse(&initializer);
}
...@@ -7,45 +7,12 @@ ...@@ -7,45 +7,12 @@
#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ #ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ #define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#include "compiler/translator/IntermNode.h" #include <GLSLANG/ShaderLang.h>
class InitializeVariables : public TIntermTraverser class TIntermNode;
{
public:
struct InitVariableInfo
{
TString name;
TType type;
InitVariableInfo(const TString &_name, const TType &_type) typedef std::vector<sh::ShaderVariable> InitVariableList;
: name(_name),
type(_type)
{
}
};
typedef TVector<InitVariableInfo> InitVariableInfoList;
InitializeVariables(const InitVariableInfoList &vars) void InitializeVariables(TIntermNode *root, const InitVariableList &vars);
: TIntermTraverser(true, false, false),
mVariables(vars),
mCodeInserted(false)
{
}
protected:
bool visitBinary(Visit, TIntermBinary *node) override { return false; }
bool visitUnary(Visit, TIntermUnary *node) override { return false; }
bool visitSelection(Visit, TIntermSelection *node) override { return false; }
bool visitLoop(Visit, TIntermLoop *node) override { return false; }
bool visitBranch(Visit, TIntermBranch *node) override { return false; }
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private:
void insertInitCode(TIntermSequence *sequence);
InitVariableInfoList mVariables;
bool mCodeInserted;
};
#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ #endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
...@@ -278,6 +278,58 @@ InterpolationType GetInterpolationType(TQualifier qualifier) ...@@ -278,6 +278,58 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
} }
} }
TType ConvertShaderVariableTypeToTType(sh::GLenum type)
{
switch (type)
{
case GL_FLOAT:
return TType(EbtFloat);
case GL_FLOAT_VEC2:
return TType(EbtFloat, 2);
case GL_FLOAT_VEC3:
return TType(EbtFloat, 3);
case GL_FLOAT_VEC4:
return TType(EbtFloat, 4);
case GL_FLOAT_MAT2:
return TType(EbtFloat, 2, 2);
case GL_FLOAT_MAT3:
return TType(EbtFloat, 3, 3);
case GL_FLOAT_MAT4:
return TType(EbtFloat, 4, 4);
case GL_FLOAT_MAT2x3:
return TType(EbtFloat, 2, 3);
case GL_FLOAT_MAT2x4:
return TType(EbtFloat, 2, 4);
case GL_FLOAT_MAT3x2:
return TType(EbtFloat, 3, 2);
case GL_FLOAT_MAT3x4:
return TType(EbtFloat, 3, 4);
case GL_FLOAT_MAT4x2:
return TType(EbtFloat, 4, 2);
case GL_FLOAT_MAT4x3:
return TType(EbtFloat, 4, 3);
case GL_INT:
return TType(EbtInt);
case GL_INT_VEC2:
return TType(EbtInt, 2);
case GL_INT_VEC3:
return TType(EbtInt, 3);
case GL_INT_VEC4:
return TType(EbtInt, 4);
case GL_UNSIGNED_INT:
return TType(EbtUInt);
case GL_UNSIGNED_INT_VEC2:
return TType(EbtUInt, 2);
case GL_UNSIGNED_INT_VEC3:
return TType(EbtUInt, 3);
case GL_UNSIGNED_INT_VEC4:
return TType(EbtUInt, 4);
default:
UNREACHABLE();
return TType();
}
}
GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable) GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
: mSymbolTable(symbolTable) : mSymbolTable(symbolTable)
{ {
......
...@@ -36,6 +36,8 @@ bool IsVaryingOut(TQualifier qualifier); ...@@ -36,6 +36,8 @@ bool IsVaryingOut(TQualifier qualifier);
bool IsVarying(TQualifier qualifier); bool IsVarying(TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier);
TString ArrayString(const TType &type); TString ArrayString(const TType &type);
// Handles only basic output variable types.
TType ConvertShaderVariableTypeToTType(sh::GLenum type);
class GetVariableTraverser : angle::NonCopyable class GetVariableTraverser : angle::NonCopyable
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment