Commit daaff1cc by Olli Etuaho Committed by Commit Bot

Set correct symbol ids when referring to GLSL built-ins

The symbol ids are fetched from the symbol table. A new utility function is added to make this more convenient. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: I780430e3386f6599503d8290c568ca9bc9cad147 Reviewed-on: https://chromium-review.googlesource.com/559535 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c7ba85c9
...@@ -432,7 +432,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -432,7 +432,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
parseContext.isMultiviewExtensionEnabled() && getShaderType() != GL_COMPUTE_SHADER) parseContext.isMultiviewExtensionEnabled() && getShaderType() != GL_COMPUTE_SHADER)
{ {
DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions, DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
outputType); outputType, symbolTable);
} }
// This pass might emit short circuits so keep it before the short circuit unfolding // This pass might emit short circuits so keep it before the short circuit unfolding
...@@ -517,7 +517,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -517,7 +517,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 && compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers")) IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
{ {
EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables); EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
symbolTable, shaderVersion);
} }
if (success) if (success)
...@@ -946,7 +947,7 @@ void TCompiler::initializeGLPosition(TIntermBlock *root) ...@@ -946,7 +947,7 @@ void TCompiler::initializeGLPosition(TIntermBlock *root)
sh::ShaderVariable var(GL_FLOAT_VEC4, 0); sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
var.name = "gl_Position"; var.name = "gl_Position";
list.push_back(var); list.push_back(var);
InitializeVariables(root, list, symbolTable, shaderVersion, shaderSpec, extensionBehavior); InitializeVariables(root, list, symbolTable, shaderVersion, extensionBehavior);
} }
void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
...@@ -988,7 +989,7 @@ void TCompiler::initializeOutputVariables(TIntermBlock *root) ...@@ -988,7 +989,7 @@ void TCompiler::initializeOutputVariables(TIntermBlock *root)
list.push_back(var); list.push_back(var);
} }
} }
InitializeVariables(root, list, symbolTable, shaderVersion, shaderSpec, extensionBehavior); InitializeVariables(root, list, symbolTable, shaderVersion, extensionBehavior);
} }
const TExtensionBehavior &TCompiler::getExtensionBehavior() const const TExtensionBehavior &TCompiler::getExtensionBehavior() const
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "compiler/translator/FindMain.h" #include "compiler/translator/FindMain.h"
#include "compiler/translator/InitializeVariables.h" #include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
...@@ -43,15 +44,16 @@ class ReplaceVariableTraverser : public TIntermTraverser ...@@ -43,15 +44,16 @@ class ReplaceVariableTraverser : public TIntermTraverser
TIntermSymbol *mNewSymbol; TIntermSymbol *mNewSymbol;
}; };
TIntermSymbol *CreateGLInstanceIDSymbol() TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
{ {
return new TIntermSymbol(0, "gl_InstanceID", TType(EbtInt, EbpHigh, EvqInstanceID)); return ReferenceBuiltInVariable("gl_InstanceID", symbolTable, 300);
} }
// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence. // Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol, void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
TIntermTyped *instanceIDSymbol, TIntermTyped *instanceIDSymbol,
unsigned numberOfViews, unsigned numberOfViews,
const TSymbolTable &symbolTable,
TIntermSequence *initializers) TIntermSequence *initializers)
{ {
// Create a signed numberOfViews node. // Create a signed numberOfViews node.
...@@ -62,7 +64,7 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol, ...@@ -62,7 +64,7 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
// Create a gl_InstanceID / numberOfViews node. // Create a gl_InstanceID / numberOfViews node.
TIntermBinary *normalizedInstanceID = TIntermBinary *normalizedInstanceID =
new TIntermBinary(EOpDiv, CreateGLInstanceIDSymbol(), numberOfViewsIntSymbol); new TIntermBinary(EOpDiv, CreateGLInstanceIDSymbol(symbolTable), numberOfViewsIntSymbol);
// Create a InstanceID = gl_InstanceID / numberOfViews node. // Create a InstanceID = gl_InstanceID / numberOfViews node.
TIntermBinary *instanceIDInitializer = TIntermBinary *instanceIDInitializer =
...@@ -71,7 +73,7 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol, ...@@ -71,7 +73,7 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
// Create a uint(gl_InstanceID) node. // Create a uint(gl_InstanceID) node.
TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence(); TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol()); glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor( TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments); TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
...@@ -132,7 +134,8 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, ...@@ -132,7 +134,8 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
unsigned numberOfViews, unsigned numberOfViews,
GLenum shaderType, GLenum shaderType,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
ShShaderOutput shaderOutput) ShShaderOutput shaderOutput,
const TSymbolTable &symbolTable)
{ {
ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
...@@ -154,7 +157,8 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, ...@@ -154,7 +157,8 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol); ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol);
TIntermSequence *initializers = new TIntermSequence(); TIntermSequence *initializers = new TIntermSequence();
InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, initializers); InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, symbolTable,
initializers);
// The AST transformation which adds the expression to select the viewport index should // The AST transformation which adds the expression to select the viewport index should
// be done only for the GLSL and ESSL output. // be done only for the GLSL and ESSL output.
......
...@@ -24,16 +24,18 @@ ...@@ -24,16 +24,18 @@
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include "angle_gl.h" #include "angle_gl.h"
class TIntermBlock;
namespace sh namespace sh
{ {
class TIntermBlock;
class TSymbolTable;
void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
unsigned numberOfViews, unsigned numberOfViews,
GLenum shaderType, GLenum shaderType,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
ShShaderOutput shaderOutput); ShShaderOutput shaderOutput,
const TSymbolTable &symbolTable);
} // namespace sh } // namespace sh
......
...@@ -26,10 +26,14 @@ namespace ...@@ -26,10 +26,14 @@ namespace
class GLFragColorBroadcastTraverser : public TIntermTraverser class GLFragColorBroadcastTraverser : public TIntermTraverser
{ {
public: public:
GLFragColorBroadcastTraverser(int maxDrawBuffers) GLFragColorBroadcastTraverser(int maxDrawBuffers,
const TSymbolTable &symbolTable,
int shaderVersion)
: TIntermTraverser(true, false, false), : TIntermTraverser(true, false, false),
mGLFragColorUsed(false), mGLFragColorUsed(false),
mMaxDrawBuffers(maxDrawBuffers) mMaxDrawBuffers(maxDrawBuffers),
mSymbolTable(symbolTable),
mShaderVersion(shaderVersion)
{ {
} }
...@@ -46,14 +50,14 @@ class GLFragColorBroadcastTraverser : public TIntermTraverser ...@@ -46,14 +50,14 @@ class GLFragColorBroadcastTraverser : public TIntermTraverser
private: private:
bool mGLFragColorUsed; bool mGLFragColorUsed;
int mMaxDrawBuffers; int mMaxDrawBuffers;
const TSymbolTable &mSymbolTable;
const int mShaderVersion;
}; };
TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
{ {
TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4); TIntermSymbol *symbol =
gl_FragDataType.setArraySize(mMaxDrawBuffers); ReferenceBuiltInVariable(TString("gl_FragData"), mSymbolTable, mShaderVersion);
TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", gl_FragDataType);
TIntermTyped *indexNode = CreateIndexNode(index); TIntermTyped *indexNode = CreateIndexNode(index);
TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode); TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
...@@ -99,10 +103,12 @@ void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root) ...@@ -99,10 +103,12 @@ void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
void EmulateGLFragColorBroadcast(TIntermBlock *root, void EmulateGLFragColorBroadcast(TIntermBlock *root,
int maxDrawBuffers, int maxDrawBuffers,
std::vector<sh::OutputVariable> *outputVariables) std::vector<sh::OutputVariable> *outputVariables,
const TSymbolTable &symbolTable,
int shaderVersion)
{ {
ASSERT(maxDrawBuffers > 1); ASSERT(maxDrawBuffers > 1);
GLFragColorBroadcastTraverser traverser(maxDrawBuffers); GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion);
root->traverse(&traverser); root->traverse(&traverser);
if (traverser.isGLFragColorUsed()) if (traverser.isGLFragColorUsed())
{ {
......
...@@ -16,13 +16,16 @@ namespace sh ...@@ -16,13 +16,16 @@ namespace sh
{ {
struct OutputVariable; struct OutputVariable;
class TIntermBlock; class TIntermBlock;
class TSymbolTable;
// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function, // Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0]. // assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0].
// If gl_FragColor is in outputVariables, it is replaced by gl_FragData. // If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
void EmulateGLFragColorBroadcast(TIntermBlock *root, void EmulateGLFragColorBroadcast(TIntermBlock *root,
int maxDrawBuffers, int maxDrawBuffers,
std::vector<OutputVariable> *outputVariables); std::vector<OutputVariable> *outputVariables,
const TSymbolTable &symbolTable,
int shaderVersion);
} }
#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ #endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
...@@ -824,8 +824,15 @@ void IdentifyBuiltIns(sh::GLenum type, ...@@ -824,8 +824,15 @@ void IdentifyBuiltIns(sh::GLenum type,
symbolTable.insert(ESSL1_BUILTINS, symbolTable.insert(ESSL1_BUILTINS,
new TVariable(NewPoolTString("gl_FragColor"), new TVariable(NewPoolTString("gl_FragColor"),
TType(EbtFloat, EbpMedium, EvqFragColor, 4))); TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); TType fragData(EbtFloat, EbpMedium, EvqFragData, 4);
fragData.setArraySize(resources.MaxDrawBuffers); if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC)
{
fragData.setArraySize(resources.MaxDrawBuffers);
}
else
{
fragData.setArraySize(1u);
}
symbolTable.insert(ESSL1_BUILTINS, symbolTable.insert(ESSL1_BUILTINS,
new TVariable(NewPoolTString("gl_FragData"), fragData)); new TVariable(NewPoolTString("gl_FragData"), fragData));
......
...@@ -87,7 +87,6 @@ void InsertInitCode(TIntermSequence *mainBody, ...@@ -87,7 +87,6 @@ void InsertInitCode(TIntermSequence *mainBody,
const InitVariableList &variables, const InitVariableList &variables,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
ShShaderSpec shaderSpec,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
{ {
for (const auto &var : variables) for (const auto &var : variables)
...@@ -99,36 +98,29 @@ void InsertInitCode(TIntermSequence *mainBody, ...@@ -99,36 +98,29 @@ void InsertInitCode(TIntermSequence *mainBody,
name = name.substr(0, pos); name = name.substr(0, pos);
} }
const TVariable *symbolInfo = nullptr; TIntermTyped *initializedSymbol = nullptr;
if (var.isBuiltIn()) if (var.isBuiltIn())
{ {
symbolInfo = initializedSymbol = ReferenceBuiltInVariable(name, symbolTable, shaderVersion);
reinterpret_cast<const TVariable *>(symbolTable.findBuiltIn(name, shaderVersion)); if (initializedSymbol->getQualifier() == EvqFragData &&
!IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
{
// If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be
// written to.
// TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up
// with a good way to do it. Right now "gl_FragData" in symbol table is initialized
// to have the array size of MaxDrawBuffers, and the initialization happens before
// the shader sets the extensions it is using.
initializedSymbol =
new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0));
}
} }
else else
{ {
symbolInfo = reinterpret_cast<const TVariable *>(symbolTable.findGlobal(name)); initializedSymbol = ReferenceGlobalVariable(name, symbolTable);
}
ASSERT(symbolInfo != nullptr);
TType type = symbolInfo->getType();
if (type.getQualifier() == EvqFragData &&
(shaderSpec == SH_WEBGL2_SPEC ||
!IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers")))
{
// Adjust the number of attachment indices which can be initialized according to the
// WebGL2 spec and extension behavior:
// - WebGL2 spec, Editor's draft May 31, 5.13 GLSL ES
// 1.00 Fragment Shader Output: "A fragment shader written in The OpenGL ES Shading
// Language, Version 1.00, that statically assigns a value to gl_FragData[n] where n
// does not equal constant value 0 must fail to compile in the WebGL 2.0 API.".
// This excerpt limits the initialization of gl_FragData to only the 0th index.
// - If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be
// written to.
type.setArraySize(1u);
} }
ASSERT(initializedSymbol != nullptr);
TIntermSymbol *initializedSymbol = new TIntermSymbol(0, name, type);
TIntermSequence *initCode = CreateInitCode(initializedSymbol); TIntermSequence *initCode = CreateInitCode(initializedSymbol);
mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end()); mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end());
} }
...@@ -191,7 +183,7 @@ class InitializeLocalsTraverser : public TIntermTraverser ...@@ -191,7 +183,7 @@ class InitializeLocalsTraverser : public TIntermTraverser
} // namespace anonymous } // namespace anonymous
TIntermSequence *CreateInitCode(const TIntermSymbol *initializedSymbol) TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol)
{ {
TIntermSequence *initCode = new TIntermSequence(); TIntermSequence *initCode = new TIntermSequence();
if (initializedSymbol->isArray()) if (initializedSymbol->isArray())
...@@ -221,12 +213,10 @@ void InitializeVariables(TIntermBlock *root, ...@@ -221,12 +213,10 @@ void InitializeVariables(TIntermBlock *root,
const InitVariableList &vars, const InitVariableList &vars,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
ShShaderSpec shaderSpec,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
{ {
TIntermBlock *body = FindMainBody(root); TIntermBlock *body = FindMainBody(root);
InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, shaderSpec, InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior);
extensionBehavior);
} }
} // namespace sh } // namespace sh
...@@ -20,7 +20,7 @@ typedef std::vector<sh::ShaderVariable> InitVariableList; ...@@ -20,7 +20,7 @@ typedef std::vector<sh::ShaderVariable> InitVariableList;
// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol // Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol
// may be an array, struct or any combination of these, as long as it contains only basic types. // may be an array, struct or any combination of these, as long as it contains only basic types.
TIntermSequence *CreateInitCode(const TIntermSymbol *initializedSymbol); TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol);
// Initialize all uninitialized local variables, so that undefined behavior is avoided. // Initialize all uninitialized local variables, so that undefined behavior is avoided.
void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion); void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion);
...@@ -32,12 +32,11 @@ void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion); ...@@ -32,12 +32,11 @@ void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion);
// 2. Initializing output variables referred to in the shader source. // 2. Initializing output variables referred to in the shader source.
// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData // Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData
// requires special handling because the number of indices which can be initialized is determined by // requires special handling because the number of indices which can be initialized is determined by
// the API spec and extension support. // enabled extensions.
void InitializeVariables(TIntermBlock *root, void InitializeVariables(TIntermBlock *root,
const InitVariableList &vars, const InitVariableList &vars,
const TSymbolTable &symbolTable, const TSymbolTable &symbolTable,
int shaderVersion, int shaderVersion,
ShShaderSpec shaderSpec,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
} // namespace sh } // namespace sh
......
...@@ -166,11 +166,21 @@ TIntermBlock *EnsureBlock(TIntermNode *node) ...@@ -166,11 +166,21 @@ TIntermBlock *EnsureBlock(TIntermNode *node)
return blockNode; return blockNode;
} }
TIntermSymbol *ReferToGlobalSymbol(const TString &name, const TSymbolTable &symbolTable) TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable)
{ {
TVariable *var = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name)); TVariable *var = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
ASSERT(var); ASSERT(var);
return new TIntermSymbol(var->getUniqueId(), name, var->getType()); return new TIntermSymbol(var->getUniqueId(), name, var->getType());
} }
TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
const TSymbolTable &symbolTable,
int shaderVersion)
{
const TVariable *var =
reinterpret_cast<const TVariable *>(symbolTable.findBuiltIn(name, shaderVersion));
ASSERT(var);
return new TIntermSymbol(var->getUniqueId(), name, var->getType());
}
} // namespace sh } // namespace sh
...@@ -35,7 +35,10 @@ TIntermConstantUnion *CreateBoolNode(bool value); ...@@ -35,7 +35,10 @@ TIntermConstantUnion *CreateBoolNode(bool value);
// If the input node is not a block node, put it inside a block node and return that. // If the input node is not a block node, put it inside a block node and return that.
TIntermBlock *EnsureBlock(TIntermNode *node); TIntermBlock *EnsureBlock(TIntermNode *node);
TIntermSymbol *ReferToGlobalSymbol(const TString &name, const TSymbolTable &symbolTable); TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable);
TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
const TSymbolTable &symbolTable,
int shaderVersion);
} // namespace sh } // namespace sh
......
...@@ -3521,16 +3521,7 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, ...@@ -3521,16 +3521,7 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
{ {
if (baseExpression->getQualifier() == EvqFragData && index > 0) if (baseExpression->getQualifier() == EvqFragData && index > 0)
{ {
if (mShaderSpec == SH_WEBGL2_SPEC) if (!isExtensionEnabled("GL_EXT_draw_buffers"))
{
// Error has been already generated if index is not const.
if (indexExpression->getQualifier() == EvqConst)
{
error(location, "array index for gl_FragData must be constant zero", "[");
}
safeIndex = 0;
}
else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
{ {
outOfRangeError(outOfRangeIndexIsError, location, outOfRangeError(outOfRangeIndexIsError, location,
"array index for gl_FragData must be zero when " "array index for gl_FragData must be zero when "
......
...@@ -35,7 +35,7 @@ void AddFieldUseStatements(const ShaderVariable &var, ...@@ -35,7 +35,7 @@ void AddFieldUseStatements(const ShaderVariable &var,
name = name.substr(0, pos); name = name.substr(0, pos);
} }
} }
TIntermSymbol *symbol = ReferToGlobalSymbol(name, symbolTable); TIntermSymbol *symbol = ReferenceGlobalVariable(name, symbolTable);
if (var.isArray()) if (var.isArray())
{ {
for (unsigned int i = 0u; i < var.arraySize; ++i) for (unsigned int i = 0u; i < var.arraySize; ++i)
...@@ -77,7 +77,7 @@ void InsertUseCode(TIntermSequence *sequence, ...@@ -77,7 +77,7 @@ void InsertUseCode(TIntermSequence *sequence,
else if (block.arraySize > 0u) else if (block.arraySize > 0u)
{ {
TString name(block.instanceName.c_str()); TString name(block.instanceName.c_str());
TIntermSymbol *arraySymbol = ReferToGlobalSymbol(name, symbolTable); TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable);
for (unsigned int i = 0u; i < block.arraySize; ++i) for (unsigned int i = 0u; i < block.arraySize; ++i)
{ {
TIntermBinary *elementSymbol = TIntermBinary *elementSymbol =
...@@ -88,7 +88,7 @@ void InsertUseCode(TIntermSequence *sequence, ...@@ -88,7 +88,7 @@ void InsertUseCode(TIntermSequence *sequence,
else else
{ {
TString name(block.instanceName.c_str()); TString name(block.instanceName.c_str());
TIntermSymbol *blockSymbol = ReferToGlobalSymbol(name, symbolTable); TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable);
InsertUseCode(block, blockSymbol, sequence); InsertUseCode(block, blockSymbol, sequence);
} }
} }
......
...@@ -361,8 +361,10 @@ TEST_F(InitOutputVariablesWebGL1FragmentShaderTest, FragData) ...@@ -361,8 +361,10 @@ TEST_F(InitOutputVariablesWebGL1FragmentShaderTest, FragData)
compileAssumeSuccess(shaderString); compileAssumeSuccess(shaderString);
VerifyOutputVariableInitializers verifier(mASTRoot); VerifyOutputVariableInitializers verifier(mASTRoot);
// In the symbol table, gl_FragData array has 2 elements. However, only the 1st one should be
// initialized.
ExpectedLValues expectedLValues = ExpectedLValues expectedLValues =
CreateIndexedLValueNodeList("gl_FragData", TType(EbtFloat, EbpMedium, EvqFragData, 4), 1); CreateIndexedLValueNodeList("gl_FragData", TType(EbtFloat, EbpMedium, EvqFragData, 4), 2);
EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[0])); EXPECT_TRUE(verifier.isExpectedLValueFound(expectedLValues[0]));
EXPECT_EQ(1u, verifier.getCandidates().size()); EXPECT_EQ(1u, verifier.getCandidates().size());
} }
......
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