Expose ViewID_OVR impostor in the fragment shader
The OVR_multiview specification states that gl_ViewID_OVR is visible
at each pipeline stage. Previously to this patch the ViewID_OVR
impostor was declared only in the vertex shader and occurrences of
gl_ViewID_OVR in the fragment shader were not being handled. The
patch addresses the issue by declaring the ViewID_OVR variable as
a vertex output in the vertex shader and as a fragment input
in the fragment shader.
BUG=angleproject:2062
TEST=angle_unittests
Change-Id: I895953e81d3632d9bb873e8ac081fdf36f63f6b7
Reviewed-on: https://chromium-review.googlesource.com/559337
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 90bb7f7..6e76fe1 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -429,9 +429,9 @@
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
if (success && (compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
- parseContext.isMultiviewExtensionEnabled() && getShaderType() == GL_VERTEX_SHADER)
+ parseContext.isMultiviewExtensionEnabled() && getShaderType() != GL_COMPUTE_SHADER)
{
- DeclareAndInitBuiltinsForInstancedMultiview(root, getNumViews());
+ DeclareAndInitBuiltinsForInstancedMultiview(root, getNumViews(), getShaderType());
}
// This pass might emit short circuits so keep it before the short circuit unfolding
diff --git a/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
index eacd289..697018a 100644
--- a/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
+++ b/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
@@ -20,28 +20,26 @@
namespace
{
-class RenameVariableAndMarkAsInternalTraverser : public TIntermTraverser
+class ReplaceVariableTraverser : public TIntermTraverser
{
public:
- RenameVariableAndMarkAsInternalTraverser(const TString &oldName, const TString &newName)
- : TIntermTraverser(true, false, false), mOldName(oldName), mNewName(newName)
+ ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol)
+ : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol)
{
}
void visitSymbol(TIntermSymbol *node) override
{
TName &name = node->getName();
- if (name.getString() == mOldName)
+ if (name.getString() == mSymbolName)
{
- node->getTypePointer()->setQualifier(EvqTemporary);
- name.setInternal(true);
- name.setString(mNewName);
+ queueReplacement(node, mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED);
}
}
private:
- TString mOldName;
- TString mNewName;
+ TString mSymbolName;
+ TIntermSymbol *mNewSymbol;
};
TIntermSymbol *CreateGLInstanceIDSymbol()
@@ -49,15 +47,14 @@
return new TIntermSymbol(0, "gl_InstanceID", TType(EbtInt, EbpHigh, EvqInstanceID));
}
-// Adds initializers for InstanceID and ViewID_OVR at the beginning of main().
-void InitializeBuiltinsInMain(TIntermBlock *root,
- TIntermSymbol *instanceIDSymbol,
- TIntermSymbol *viewIDSymbol,
- unsigned numberOfViews)
+void InitializeViewIDAndInstanceID(TIntermBlock *root,
+ TIntermTyped *viewIDSymbol,
+ TIntermTyped *instanceIDSymbol,
+ unsigned numberOfViews)
{
// Create a signed numberOfViews node.
TConstantUnion *numberOfViewsConstant = new TConstantUnion();
- numberOfViewsConstant->setIConst(numberOfViews);
+ numberOfViewsConstant->setIConst(static_cast<int>(numberOfViews));
TIntermConstantUnion *numberOfViewsIntSymbol =
new TIntermConstantUnion(numberOfViewsConstant, TType(EbtInt, EbpHigh, EvqConst));
@@ -67,15 +64,15 @@
// Create a InstanceID = gl_InstanceID / numberOfViews node.
TIntermBinary *instanceIDInitializer =
- new TIntermBinary(EOpAssign, instanceIDSymbol, normalizedInstanceID);
+ new TIntermBinary(EOpAssign, instanceIDSymbol->deepCopy(), normalizedInstanceID);
// Create a uint(gl_InstanceID) node.
- TIntermSequence *instanceIDSymbolCastArguments = new TIntermSequence();
- instanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol());
- TIntermAggregate *instanceIDAsUint = TIntermAggregate::CreateConstructor(
- TType(EbtUInt, EbpHigh, EvqTemporary), instanceIDSymbolCastArguments);
+ TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
+ glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol());
+ TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
+ TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
- // Create a unsigned numberOfViews node.
+ // Create an unsigned numberOfViews node.
TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion();
numberOfViewsUnsignedConstant->setUConst(numberOfViews);
TIntermConstantUnion *numberOfViewsUintSymbol =
@@ -83,79 +80,60 @@
// Create a uint(gl_InstanceID) % numberOfViews node.
TIntermBinary *normalizedViewID =
- new TIntermBinary(EOpIMod, instanceIDAsUint, numberOfViewsUintSymbol);
+ new TIntermBinary(EOpIMod, glInstanceIDAsUint, numberOfViewsUintSymbol);
// Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
- TIntermBinary *viewIDInitializer = new TIntermBinary(EOpAssign, viewIDSymbol, normalizedViewID);
+ TIntermBinary *viewIDInitializer =
+ new TIntermBinary(EOpAssign, viewIDSymbol->deepCopy(), normalizedViewID);
- // Add nodes to sequence and insert into main.
- TIntermSequence *initializers = new TIntermSequence();
- initializers->push_back(viewIDInitializer);
- initializers->push_back(instanceIDInitializer);
-
- // Insert init code as a block at the beginning of the main() function.
- TIntermBlock *initGlobalsBlock = new TIntermBlock();
- initGlobalsBlock->getSequence()->swap(*initializers);
-
- TIntermFunctionDefinition *main = FindMain(root);
- ASSERT(main != nullptr);
- TIntermBlock *mainBody = main->getBody();
- ASSERT(mainBody != nullptr);
- mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsBlock);
+ // Add initializers at the beginning of main().
+ TIntermBlock *mainBody = FindMainBody(root);
+ mainBody->getSequence()->insert(mainBody->getSequence()->begin(), instanceIDInitializer);
+ mainBody->getSequence()->insert(mainBody->getSequence()->begin(), viewIDInitializer);
}
-// Adds declarations for ViewID_OVR and InstanceID in global scope at the beginning of
-// the shader.
-void DeclareBuiltinsInGlobalScope(TIntermBlock *root,
- TIntermSymbol *instanceIDSymbol,
- TIntermSymbol *viewIDSymbol)
+// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode.
+void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode)
+{
+ ReplaceVariableTraverser traverser(symbolName, newSymbolNode);
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode)
{
TIntermSequence *globalSequence = root->getSequence();
-
- TIntermDeclaration *instanceIDDeclaration = new TIntermDeclaration();
- instanceIDDeclaration->appendDeclarator(instanceIDSymbol);
-
- TIntermDeclaration *viewIDOVRDeclaration = new TIntermDeclaration();
- viewIDOVRDeclaration->appendDeclarator(viewIDSymbol);
-
- globalSequence->insert(globalSequence->begin(), viewIDOVRDeclaration);
- globalSequence->insert(globalSequence->begin(), instanceIDDeclaration);
-}
-
-// Replaces every occurrence of gl_InstanceID with InstanceID, sets the name to internal
-// and changes the qualifier from EvqInstanceID to EvqTemporary.
-void RenameGLInstanceIDAndMarkAsInternal(TIntermBlock *root)
-{
- RenameVariableAndMarkAsInternalTraverser traverser("gl_InstanceID", "InstanceID");
- root->traverse(&traverser);
-}
-
-// Replaces every occurrence of gl_ViewID_OVR with ViewID_OVR, sets the name to internal
-// and changes the qualifier from EvqViewIDOVR to EvqTemporary.
-void RenameGLViewIDAndMarkAsInternal(TIntermBlock *root)
-{
- RenameVariableAndMarkAsInternalTraverser traverser("gl_ViewID_OVR", "ViewID_OVR");
- root->traverse(&traverser);
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->appendDeclarator(typedNode->deepCopy());
+ globalSequence->insert(globalSequence->begin(), declaration);
}
} // namespace
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, unsigned numberOfViews)
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+ unsigned numberOfViews,
+ GLenum shaderType)
{
- TIntermSymbol *instanceIDSymbol = new TIntermSymbol(TSymbolTable::nextUniqueId(), "InstanceID",
- TType(EbtInt, EbpHigh, EvqGlobal));
- instanceIDSymbol->setInternal(true);
+ ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
+ TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
TIntermSymbol *viewIDSymbol = new TIntermSymbol(TSymbolTable::nextUniqueId(), "ViewID_OVR",
- TType(EbtUInt, EbpHigh, EvqGlobal));
+ TType(EbtUInt, EbpHigh, viewIDQualifier));
viewIDSymbol->setInternal(true);
- // Renaming the variables should happen before adding the initializers.
- RenameGLInstanceIDAndMarkAsInternal(root);
- DeclareBuiltinsInGlobalScope(root, instanceIDSymbol, viewIDSymbol);
- InitializeBuiltinsInMain(root, instanceIDSymbol->deepCopy()->getAsSymbolNode(),
- viewIDSymbol->deepCopy()->getAsSymbolNode(), numberOfViews);
- RenameGLViewIDAndMarkAsInternal(root);
+ DeclareGlobalVariable(root, viewIDSymbol);
+ ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol);
+ if (shaderType == GL_VERTEX_SHADER)
+ {
+ // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
+ // InstanceID and ViewID.
+ TIntermSymbol *instanceIDSymbol = new TIntermSymbol(
+ TSymbolTable::nextUniqueId(), "InstanceID", TType(EbtInt, EbpHigh, EvqGlobal));
+ instanceIDSymbol->setInternal(true);
+ DeclareGlobalVariable(root, instanceIDSymbol);
+ ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol);
+ InitializeViewIDAndInstanceID(root, viewIDSymbol, instanceIDSymbol, numberOfViews);
+ }
}
} // namespace sh
\ No newline at end of file
diff --git a/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h b/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
index 25937ec..b72dc0a 100644
--- a/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
+++ b/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
@@ -3,24 +3,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// This pass applies the following modifications to the AST:
-// 1) Replaces every occurrence of gl_InstanceID with InstanceID and marks InstanceID as internal.
-// 2) Adds declarations of the global variables ViewID_OVR and InstanceID.
-// 3) Initializes ViewID_OVR and InstanceID depending on the number of views.
-// 4) Replaces every occurrence of gl_ViewID_OVR with ViewID_OVR and marks ViewID_OVR as internal.
-// The pass should be executed before any variables get collected so that usage of gl_InstanceID is
-// recorded.
+// Regardless of the shader type, the following AST transformations are applied:
+// - Add declaration of View_ID_OVR.
+// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and
+// declare it as a flat varying.
+// If the shader type is a vertex shader, the following AST transformations are applied:
+// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set
+// its qualifier to EvqTemporary.
+// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass
+// should be executed before any variables get collected so that usage of gl_InstanceID is recorded.
//
#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
+#include "angle_gl.h"
+
class TIntermBlock;
namespace sh
{
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root, unsigned numberOfViews);
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+ unsigned numberOfViews,
+ GLenum shaderType);
} // namespace sh
diff --git a/src/compiler/translator/FindMain.cpp b/src/compiler/translator/FindMain.cpp
index f73666b..7417fba 100644
--- a/src/compiler/translator/FindMain.cpp
+++ b/src/compiler/translator/FindMain.cpp
@@ -26,4 +26,13 @@
return nullptr;
}
+TIntermBlock *FindMainBody(TIntermBlock *root)
+{
+ TIntermFunctionDefinition *main = FindMain(root);
+ ASSERT(main != nullptr);
+ TIntermBlock *mainBody = main->getBody();
+ ASSERT(mainBody != nullptr);
+ return mainBody;
+}
+
} // namespace sh
diff --git a/src/compiler/translator/FindMain.h b/src/compiler/translator/FindMain.h
index fb06583..bf2c45d 100644
--- a/src/compiler/translator/FindMain.h
+++ b/src/compiler/translator/FindMain.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-// FindMain.h: Find the main() function definition in a given AST.
+// FindMain.h: Adds functions to get the main function definition and its body.
#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_
#define COMPILER_TRANSLATOR_FINDMAIN_H_
@@ -16,6 +16,7 @@
class TIntermFunctionDefinition;
TIntermFunctionDefinition *FindMain(TIntermBlock *root);
+TIntermBlock *FindMainBody(TIntermBlock *root);
} // namespace sh