Commit 6ec55494 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Use AST transformation for gathering default uniforms

... instead of generating text. This will keep the tree in a consistent state, as previously the references to uniform values where to TVariable's whose declarations were removed. Bug: angleproject:2461 Bug: angleproject:4889 Change-Id: I2ef3787dede371514a5f495f4cc8fc67ea45f451 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2815564 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent faa86bc9
...@@ -50,6 +50,18 @@ namespace sh ...@@ -50,6 +50,18 @@ namespace sh
namespace namespace
{ {
constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord");
constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragCoord");
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
{gl::ShaderType::Vertex, vk::kDefaultUniformsNameVS},
{gl::ShaderType::TessControl, vk::kDefaultUniformsNameTCS},
{gl::ShaderType::TessEvaluation, vk::kDefaultUniformsNameTES},
{gl::ShaderType::Geometry, vk::kDefaultUniformsNameGS},
{gl::ShaderType::Fragment, vk::kDefaultUniformsNameFS},
{gl::ShaderType::Compute, vk::kDefaultUniformsNameCS},
};
// This traverses nodes, find the struct ones and add their declarations to the sink. It also // This traverses nodes, find the struct ones and add their declarations to the sink. It also
// removes the nodes from the tree as it processes them. // removes the nodes from the tree as it processes them.
class DeclareStructTypesTraverser : public TIntermTraverser class DeclareStructTypesTraverser : public TIntermTraverser
...@@ -97,89 +109,122 @@ class DeclareStructTypesTraverser : public TIntermTraverser ...@@ -97,89 +109,122 @@ class DeclareStructTypesTraverser : public TIntermTraverser
TOutputVulkanGLSL *mOutputVulkanGLSL; TOutputVulkanGLSL *mOutputVulkanGLSL;
}; };
class DeclareDefaultUniformsTraverser : public TIntermTraverser bool IsDefaultUniform(const TType &type)
{
return type.getQualifier() == EvqUniform && type.getInterfaceBlock() == nullptr &&
!IsOpaqueType(type.getBasicType());
}
class ReplaceDefaultUniformsTraverser : public TIntermTraverser
{ {
public: public:
DeclareDefaultUniformsTraverser(TInfoSinkBase *sink, ReplaceDefaultUniformsTraverser(const VariableReplacementMap &variableMap)
ShHashFunction64 hashFunction, : TIntermTraverser(true, false, false), mVariableMap(variableMap)
NameMap *nameMap)
: TIntermTraverser(true, true, true),
mSink(sink),
mHashFunction(hashFunction),
mNameMap(nameMap),
mInDefaultUniform(false)
{} {}
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
{ {
const TIntermSequence &sequence = *(node->getSequence()); const TIntermSequence &sequence = *(node->getSequence());
// TODO(jmadill): Compound declarations.
ASSERT(sequence.size() == 1);
TIntermTyped *variable = sequence.front()->getAsTyped(); TIntermTyped *variable = sequence.front()->getAsTyped();
const TType &type = variable->getType(); const TType &type = variable->getType();
bool isUniform = type.getQualifier() == EvqUniform && !type.isInterfaceBlock() &&
!IsOpaqueType(type.getBasicType());
if (visit == PreVisit) if (IsDefaultUniform(type))
{
if (isUniform)
{
(*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " ";
mInDefaultUniform = true;
}
}
else if (visit == InVisit)
{
mInDefaultUniform = isUniform;
}
else if (visit == PostVisit)
{ {
if (isUniform) // Remove the uniform declaration.
{ TIntermSequence emptyReplacement;
(*mSink) << ";\n"; mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node,
std::move(emptyReplacement));
// Remove the uniform declaration from the tree so it isn't parsed again. return false;
TIntermSequence emptyReplacement;
mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node,
std::move(emptyReplacement));
}
mInDefaultUniform = false;
} }
return true; return true;
} }
void visitSymbol(TIntermSymbol *symbol) override void visitSymbol(TIntermSymbol *symbol) override
{ {
if (mInDefaultUniform) const TVariable &variable = symbol->variable();
const TType &type = variable.getType();
if (!IsDefaultUniform(type) || variable.name().beginsWith("gl_"))
{ {
const ImmutableString &name = symbol->variable().name(); return;
ASSERT(!name.beginsWith("gl_"));
(*mSink) << HashName(&symbol->variable(), mHashFunction, mNameMap)
<< ArrayString(symbol->getType());
} }
ASSERT(mVariableMap.count(&variable) > 0);
queueReplacement(mVariableMap.at(&variable)->deepCopy(), OriginalNode::IS_DROPPED);
} }
private: private:
TInfoSinkBase *mSink; const VariableReplacementMap &mVariableMap;
ShHashFunction64 mHashFunction;
NameMap *mNameMap;
bool mInDefaultUniform;
}; };
constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord"); bool DeclareDefaultUniforms(TCompiler *compiler,
constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragCoord"); TIntermBlock *root,
TSymbolTable *symbolTable,
gl::ShaderType shaderType)
{
// First, collect all default uniforms and declare a uniform block.
TFieldList *uniformList = new TFieldList;
TVector<const TVariable *> uniformVars;
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = { for (TIntermNode *node : *root->getSequence())
{gl::ShaderType::Vertex, vk::kDefaultUniformsNameVS}, {
{gl::ShaderType::TessControl, vk::kDefaultUniformsNameTCS}, TIntermDeclaration *decl = node->getAsDeclarationNode();
{gl::ShaderType::TessEvaluation, vk::kDefaultUniformsNameTES}, if (decl == nullptr)
{gl::ShaderType::Geometry, vk::kDefaultUniformsNameGS}, {
{gl::ShaderType::Fragment, vk::kDefaultUniformsNameFS}, continue;
{gl::ShaderType::Compute, vk::kDefaultUniformsNameCS}, }
};
const TIntermSequence &sequence = *(decl->getSequence());
TIntermSymbol *symbol = sequence.front()->getAsSymbolNode();
if (symbol == nullptr)
{
continue;
}
const TType &type = symbol->getType();
if (IsDefaultUniform(type))
{
TType *fieldType = new TType(type);
fieldType->setPrecision(EbpUndefined);
uniformList->push_back(new TField(fieldType, symbol->getName(), symbol->getLine(),
symbol->variable().symbolType()));
uniformVars.push_back(&symbol->variable());
}
}
TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
layoutQualifier.blockStorage = EbsStd140;
const TVariable *uniformBlock = DeclareInterfaceBlock(
root, symbolTable, uniformList, EvqUniform, layoutQualifier, TMemoryQualifier::Create(), 0,
ImmutableString(kDefaultUniformNames[shaderType]), ImmutableString(""));
// Create a map from the uniform variables to new variables that reference the fields of the
// block.
VariableReplacementMap variableMap;
for (const TVariable *variable : uniformVars)
{
TType *replacementType = new TType(variable->getType());
replacementType->setPrecision(EbpUndefined);
replacementType->setInterfaceBlock(uniformBlock->getType().getInterfaceBlock());
TVariable *replacementVariable =
new TVariable(symbolTable, variable->name(), replacementType, variable->symbolType());
variableMap[variable] = new TIntermSymbol(replacementVariable);
}
// Finally transform the AST and make sure references to the uniforms are replaced with the new
// variables.
ReplaceDefaultUniformsTraverser defaultTraverser(variableMap);
root->traverse(&defaultTraverser);
return defaultTraverser.updateTree(compiler, root);
}
// Replaces a builtin variable with a version that is rotated and corrects the X and Y coordinates. // Replaces a builtin variable with a version that is rotated and corrects the X and Y coordinates.
ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler, ANGLE_NO_DISCARD bool RotateAndFlipBuiltinVariable(TCompiler *compiler,
...@@ -529,8 +574,8 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -529,8 +574,8 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
varName << vk::kXfbEmulationBufferName; varName << vk::kXfbEmulationBufferName;
varName.appendDecimal(bufferIndex); varName.appendDecimal(bufferIndex);
DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, TMemoryQualifier::Create(), DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, TLayoutQualifier::Create(),
0, blockName, varName); TMemoryQualifier::Create(), 0, blockName, varName);
} }
return compiler->validateAST(root); return compiler->validateAST(root);
...@@ -890,20 +935,10 @@ bool TranslatorVulkan::translateImpl(TInfoSinkBase &sink, ...@@ -890,20 +935,10 @@ bool TranslatorVulkan::translateImpl(TInfoSinkBase &sink,
if (defaultUniformCount > 0) if (defaultUniformCount > 0)
{ {
// This transformation leaves the tree in an inconsistent state. TODO: anglebug.com/4889 if (!DeclareDefaultUniforms(this, root, &getSymbolTable(), packedShaderType))
mValidateASTOptions.validateVariableReferences = false;
sink << "\nlayout(set=0, binding=" << outputGLSL->nextUnusedBinding()
<< ", std140) uniform " << kDefaultUniformNames[packedShaderType] << "\n{\n";
DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap());
root->traverse(&defaultTraverser);
if (!defaultTraverser.updateTree(this, root))
{ {
return false; return false;
} }
sink << "};\n";
} }
if (getShaderType() == GL_COMPUTE_SHADER) if (getShaderType() == GL_COMPUTE_SHADER)
......
...@@ -45,8 +45,9 @@ const TVariable *DeclareAtomicCountersBuffers(TIntermBlock *root, TSymbolTable * ...@@ -45,8 +45,9 @@ const TVariable *DeclareAtomicCountersBuffers(TIntermBlock *root, TSymbolTable *
// Define a storage block "ANGLEAtomicCounters" with instance name "atomicCounters". // Define a storage block "ANGLEAtomicCounters" with instance name "atomicCounters".
return DeclareInterfaceBlock( return DeclareInterfaceBlock(
root, symbolTable, fieldList, EvqBuffer, coherentMemory, kMaxAtomicCounterBuffers, root, symbolTable, fieldList, EvqBuffer, TLayoutQualifier::Create(), coherentMemory,
ImmutableString(vk::kAtomicCountersBlockName), kAtomicCountersVarName); kMaxAtomicCounterBuffers, ImmutableString(vk::kAtomicCountersBlockName),
kAtomicCountersVarName);
} }
TIntermTyped *CreateUniformBufferOffset(const TIntermTyped *uniformBufferOffsets, int binding) TIntermTyped *CreateUniformBufferOffset(const TIntermTyped *uniformBufferOffsets, int binding)
......
...@@ -64,9 +64,10 @@ bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbol ...@@ -64,9 +64,10 @@ bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbol
} }
// Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
mDriverUniforms = DeclareInterfaceBlock( mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
root, symbolTable, driverFieldList, EvqUniform, TMemoryQualifier::Create(), 0, TLayoutQualifier::Create(), TMemoryQualifier::Create(),
ImmutableString(vk::kDriverUniformsBlockName), ImmutableString(vk::kDriverUniformsVarName)); 0, ImmutableString(vk::kDriverUniformsBlockName),
ImmutableString(vk::kDriverUniformsVarName));
return mDriverUniforms != nullptr; return mDriverUniforms != nullptr;
} }
...@@ -148,9 +149,10 @@ bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbo ...@@ -148,9 +149,10 @@ bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbo
TFieldList *driverFieldList = createUniformFields(symbolTable); TFieldList *driverFieldList = createUniformFields(symbolTable);
// Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
mDriverUniforms = DeclareInterfaceBlock( mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
root, symbolTable, driverFieldList, EvqUniform, TMemoryQualifier::Create(), 0, TLayoutQualifier::Create(), TMemoryQualifier::Create(),
ImmutableString(vk::kDriverUniformsBlockName), ImmutableString(vk::kDriverUniformsVarName)); 0, ImmutableString(vk::kDriverUniformsBlockName),
ImmutableString(vk::kDriverUniformsVarName));
return mDriverUniforms != nullptr; return mDriverUniforms != nullptr;
} }
......
...@@ -228,14 +228,14 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, ...@@ -228,14 +228,14 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
TFieldList *fieldList, TFieldList *fieldList,
TQualifier qualifier, TQualifier qualifier,
const TLayoutQualifier &layoutQualifier,
const TMemoryQualifier &memoryQualifier, const TMemoryQualifier &memoryQualifier,
uint32_t arraySize, uint32_t arraySize,
const ImmutableString &blockTypeName, const ImmutableString &blockTypeName,
const ImmutableString &blockVariableName) const ImmutableString &blockVariableName)
{ {
// Define an interface block. // Define an interface block.
TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
symbolTable, blockTypeName, fieldList, layoutQualifier, SymbolType::AngleInternal); symbolTable, blockTypeName, fieldList, layoutQualifier, SymbolType::AngleInternal);
// Turn the inteface block into a declaration. // Turn the inteface block into a declaration.
...@@ -247,8 +247,9 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, ...@@ -247,8 +247,9 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
} }
TIntermDeclaration *interfaceBlockDecl = new TIntermDeclaration; TIntermDeclaration *interfaceBlockDecl = new TIntermDeclaration;
TVariable *interfaceBlockVar = new TVariable(symbolTable, blockVariableName, interfaceBlockType, TVariable *interfaceBlockVar =
SymbolType::AngleInternal); new TVariable(symbolTable, blockVariableName, interfaceBlockType,
blockVariableName.empty() ? SymbolType::Empty : SymbolType::AngleInternal);
TIntermSymbol *interfaceBlockDeclarator = new TIntermSymbol(interfaceBlockVar); TIntermSymbol *interfaceBlockDeclarator = new TIntermSymbol(interfaceBlockVar);
interfaceBlockDecl->appendDeclarator(interfaceBlockDeclarator); interfaceBlockDecl->appendDeclarator(interfaceBlockDeclarator);
......
...@@ -49,6 +49,7 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, ...@@ -49,6 +49,7 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
TFieldList *fieldList, TFieldList *fieldList,
TQualifier qualifier, TQualifier qualifier,
const TLayoutQualifier &layoutQualifier,
const TMemoryQualifier &memoryQualifier, const TMemoryQualifier &memoryQualifier,
uint32_t arraySize, uint32_t arraySize,
const ImmutableString &blockTypeName, const ImmutableString &blockTypeName,
......
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