Add shader translator support for OVR_multiview
The OVR_multiview and OVR_multiview2 extensions add gl_ViewID_OVR to
shaders. gl_ViewID_OVR can be translated either as is in GLSL output
or as a uniform by setting the SH_TRANSLATE_VIEWID_OVR_AS_UNIFORM
compiler flag.
If WebGL output is selected, the shaders will be validated according
to proposed rules in the WEBGL_multiview spec.
BUG=angleproject:1669
TEST=angle_unittests
Change-Id: I19ea3a6c8b4edb78be03f1a50a96bfef018870d0
Reviewed-on: https://chromium-review.googlesource.com/422848
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index df8ce9f..6e7f854 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -106,7 +106,10 @@
mUsesSecondaryOutputs(false),
mMinProgramTexelOffset(resources.MinProgramTexelOffset),
mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
+ mMultiviewAvailable(resources.OVR_multiview == 1),
mComputeShaderLocalSizeDeclared(false),
+ mNumViews(-1),
+ mMaxNumViews(resources.MaxViewsOVR),
mDeclaringFunction(false)
{
mComputeShaderLocalSize.fill(-1);
@@ -1085,6 +1088,12 @@
// In GLSL ES, an extension's default behavior is "disable".
if (iter->second == EBhDisable || iter->second == EBhUndefined)
{
+ // TODO(oetuaho@nvidia.com): This is slightly hacky. Might be better if symbols could be
+ // associated with more than one extension.
+ if (extension == "GL_OVR_multiview")
+ {
+ return checkCanUseExtension(line, "GL_OVR_multiview2");
+ }
error(line, "extension is disabled", extension.c_str());
return false;
}
@@ -1481,6 +1490,14 @@
{
const TVariable *variable = getNamedVariable(location, name, symbol);
+ if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
+ mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
+ {
+ // WEBGL_multiview spec
+ error(location, "Need to enable OVR_multiview2 to use gl_ViewID_OVR in fragment shader",
+ "gl_ViewID_OVR");
+ }
+
if (variable->getConstPointer())
{
const TConstantUnion *constArray = variable->getConstPointer();
@@ -2315,10 +2332,37 @@
mComputeShaderLocalSizeDeclared = true;
}
+ else if (mMultiviewAvailable &&
+ (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
+ typeQualifier.qualifier == EvqVertexIn)
+ {
+ // This error is only specified in WebGL, but tightens unspecified behavior in the native
+ // specification.
+ if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
+ {
+ error(typeQualifier.line, "Number of views does not match the previous declaration",
+ "layout");
+ return;
+ }
+
+ if (layoutQualifier.numViews == -1)
+ {
+ error(typeQualifier.line, "No num_views specified", "layout");
+ return;
+ }
+
+ if (layoutQualifier.numViews > mMaxNumViews)
+ {
+ error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
+ "layout");
+ return;
+ }
+
+ mNumViews = layoutQualifier.numViews;
+ }
else
{
-
- if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
+ if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
{
return;
}
@@ -2337,7 +2381,7 @@
return;
}
- checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
+ checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
if (layoutQualifier.matrixPacking != EmpUnspecified)
{
@@ -3348,6 +3392,20 @@
(*localSize)[index] = intValue;
}
+void TParseContext::parseNumViews(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numViews)
+{
+ // This error is only specified in WebGL, but tightens unspecified behavior in the native
+ // specification.
+ if (intValue < 1)
+ {
+ error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
+ }
+ *numViews = intValue;
+}
+
TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine,
int intValue,
@@ -3386,6 +3444,12 @@
parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
&qualifier.localSize);
}
+ else if (qualifierType == "num_views" && mMultiviewAvailable &&
+ (isExtensionEnabled("GL_OVR_multiview") || isExtensionEnabled("GL_OVR_multiview2")) &&
+ mShaderType == GL_VERTEX_SHADER)
+ {
+ parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
+ }
else
{
error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());