Vulkan: Add driver uniforms to shader.
Bug: angleproject:2717
Change-Id: I542f3b0f2de21857d7fea0267f07d2d0eec78a8c
Reviewed-on: https://chromium-review.googlesource.com/1131567
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Luc Ferron <lucferron@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 24663d0..d72b867 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -595,8 +595,6 @@
node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
- ASSERT(interfaceBlock->symbolType() == SymbolType::UserDefined ||
- interfaceBlock->name() == "gl_PerVertex");
out << hashFieldName(field);
visitChildren = false;
}
diff --git a/src/compiler/translator/OutputVulkanGLSL.cpp b/src/compiler/translator/OutputVulkanGLSL.cpp
index 99b0e40..798e64c 100644
--- a/src/compiler/translator/OutputVulkanGLSL.cpp
+++ b/src/compiler/translator/OutputVulkanGLSL.cpp
@@ -46,7 +46,7 @@
bool needsCustomLayout =
(type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
- IsSampler(type.getBasicType()));
+ IsSampler(type.getBasicType()) || type.isInterfaceBlock());
if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
{
@@ -58,8 +58,6 @@
// This isn't super clean, but it gets the job done.
// See corresponding code in GlslangWrapper.cpp.
- // TODO(jmadill): Ensure declarations are separated.
-
TIntermSymbol *symbol = variable->getAsSymbolNode();
ASSERT(symbol);
@@ -99,9 +97,7 @@
}
TInfoSinkBase &out = objSink();
- out << "@@ QUALIFIER-";
- out << symbol->name().data();
- out << " @@ ";
+ out << "@@ QUALIFIER-" << symbol->name().data() << " @@ ";
}
void TOutputVulkanGLSL::writeStructType(const TStructure *structure)
@@ -112,5 +108,4 @@
objSink() << ";\n";
}
}
-
} // namespace sh
diff --git a/src/compiler/translator/TranslatorVulkan.cpp b/src/compiler/translator/TranslatorVulkan.cpp
index 8155105..9c82f99 100644
--- a/src/compiler/translator/TranslatorVulkan.cpp
+++ b/src/compiler/translator/TranslatorVulkan.cpp
@@ -256,6 +256,44 @@
// Append the assignment as a statement at the end of the shader.
RunAtTheEndOfShader(root, assignment, symbolTable);
}
+
+// The AddDriverUniformsToShader operation adds an internal uniform block to a shader. The driver
+// block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms
+// variable.
+const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable)
+{
+ // This field list mirrors the structure of ContextVk::DriverUniforms.
+ TFieldList *driverFieldList = new TFieldList;
+
+ // Add a vec4 field "viewport" to the driver uniform fields.
+ TType *driverViewportType = new TType(EbtFloat, 4);
+ TField *driverViewportSize = new TField(driverViewportType, ImmutableString("viewport"),
+ TSourceLoc(), SymbolType::AngleInternal);
+ driverFieldList->push_back(driverViewportSize);
+
+ // Define a driver uniform block "ANGLEUniformBlock".
+ TLayoutQualifier driverLayoutQualifier = TLayoutQualifier::Create();
+ TInterfaceBlock *interfaceBlock =
+ new TInterfaceBlock(symbolTable, ImmutableString("ANGLEUniformBlock"), driverFieldList,
+ driverLayoutQualifier, SymbolType::AngleInternal);
+
+ // Make the inteface block into a declaration. Use instance name "ANGLEUniforms".
+ TType *interfaceBlockType = new TType(interfaceBlock, EvqUniform, driverLayoutQualifier);
+ TIntermDeclaration *driverUniformsDecl = new TIntermDeclaration;
+ TVariable *driverUniformsVar = new TVariable(symbolTable, ImmutableString("ANGLEUniforms"),
+ interfaceBlockType, SymbolType::AngleInternal);
+ TIntermSymbol *driverUniformsDeclarator = new TIntermSymbol(driverUniformsVar);
+ driverUniformsDecl->appendDeclarator(driverUniformsDeclarator);
+
+ // Insert the declarations before Main.
+ TIntermSequence *insertSequence = new TIntermSequence;
+ insertSequence->push_back(driverUniformsDecl);
+
+ size_t mainIndex = FindMainIndex(root);
+ root->insertChildNodes(mainIndex, *insertSequence);
+
+ return driverUniformsVar;
+}
} // anonymous namespace
TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
@@ -315,6 +353,8 @@
sink << "};\n";
}
+ AddDriverUniformsToShader(root, &getSymbolTable());
+
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used.
if (getShaderType() == GL_FRAGMENT_SHADER)
diff --git a/src/compiler/translator/tree_util/FindMain.cpp b/src/compiler/translator/tree_util/FindMain.cpp
index 9823a01..0e3023b 100644
--- a/src/compiler/translator/tree_util/FindMain.cpp
+++ b/src/compiler/translator/tree_util/FindMain.cpp
@@ -14,6 +14,21 @@
namespace sh
{
+size_t FindMainIndex(TIntermBlock *root)
+{
+ const TIntermSequence &sequence = *root->getSequence();
+ for (size_t index = 0; index < sequence.size(); ++index)
+ {
+ TIntermNode *node = sequence[index];
+ TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
+ if (nodeFunction != nullptr && nodeFunction->getFunction()->isMain())
+ {
+ return index;
+ }
+ }
+ return std::numeric_limits<size_t>::max();
+}
+
TIntermFunctionDefinition *FindMain(TIntermBlock *root)
{
for (TIntermNode *node : *root->getSequence())
diff --git a/src/compiler/translator/tree_util/FindMain.h b/src/compiler/translator/tree_util/FindMain.h
index f619e6e..a313315 100644
--- a/src/compiler/translator/tree_util/FindMain.h
+++ b/src/compiler/translator/tree_util/FindMain.h
@@ -9,15 +9,16 @@
#ifndef COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_
#define COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_
+#include <cstddef>
+
namespace sh
{
-
class TIntermBlock;
class TIntermFunctionDefinition;
+size_t FindMainIndex(TIntermBlock *root);
TIntermFunctionDefinition *FindMain(TIntermBlock *root);
TIntermBlock *FindMainBody(TIntermBlock *root);
-
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEUTIL_FINDMAIN_H_
\ No newline at end of file
diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
index fdb3d8c..a6d7d13 100644
--- a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
+++ b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
@@ -299,6 +299,15 @@
}
}
+ // Substitute layout and qualifier strings for the driver uniforms block.
+ constexpr char kDriverBlockLayoutString[] = "set = 2, binding = 0";
+ constexpr char kDriverBlockName[] = "ANGLEUniforms";
+ InsertLayoutSpecifierString(&vertexSource, kDriverBlockName, kDriverBlockLayoutString);
+ InsertLayoutSpecifierString(&fragmentSource, kDriverBlockName, kDriverBlockLayoutString);
+
+ InsertQualifierSpecifierString(&vertexSource, kDriverBlockName, kUniformQualifier);
+ InsertQualifierSpecifierString(&fragmentSource, kDriverBlockName, kUniformQualifier);
+
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
std::array<int, 2> lengths = {
{static_cast<int>(vertexSource.length()), static_cast<int>(fragmentSource.length())}};