• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // OVR_multiview2_test.cpp:
7 //   Test that shaders with gl_ViewID_OVR are validated correctly.
8 //
9 
10 #include "GLSLANG/ShaderLang.h"
11 #include "compiler/translator/tree_util/IntermTraverse.h"
12 #include "tests/test_utils/ShaderCompileTreeTest.h"
13 #include "tests/test_utils/compiler_test.h"
14 
15 using namespace sh;
16 
17 namespace
18 {
19 
20 class SymbolOccurrenceCounter : public TIntermTraverser
21 {
22   public:
SymbolOccurrenceCounter()23     SymbolOccurrenceCounter() : TIntermTraverser(true, false, false), mNumberOfOccurrences(0u) {}
24 
visitSymbol(TIntermSymbol * node)25     void visitSymbol(TIntermSymbol *node) override
26     {
27         if (shouldCountSymbol(node))
28         {
29             ++mNumberOfOccurrences;
30         }
31     }
32 
33     virtual bool shouldCountSymbol(const TIntermSymbol *node) const = 0;
34 
getNumberOfOccurrences() const35     unsigned getNumberOfOccurrences() const { return mNumberOfOccurrences; }
36 
37   private:
38     unsigned mNumberOfOccurrences;
39 };
40 
41 class SymbolOccurrenceCounterByQualifier : public SymbolOccurrenceCounter
42 {
43   public:
SymbolOccurrenceCounterByQualifier(TQualifier symbolQualifier)44     SymbolOccurrenceCounterByQualifier(TQualifier symbolQualifier)
45         : mSymbolQualifier(symbolQualifier)
46     {}
47 
shouldCountSymbol(const TIntermSymbol * node) const48     bool shouldCountSymbol(const TIntermSymbol *node) const override
49     {
50         return node->getQualifier() == mSymbolQualifier;
51     }
52 
53   private:
54     TQualifier mSymbolQualifier;
55 };
56 
57 class SymbolOccurrenceCounterByName : public SymbolOccurrenceCounter
58 {
59   public:
SymbolOccurrenceCounterByName(const ImmutableString & symbolName)60     SymbolOccurrenceCounterByName(const ImmutableString &symbolName) : mSymbolName(symbolName) {}
61 
shouldCountSymbol(const TIntermSymbol * node) const62     bool shouldCountSymbol(const TIntermSymbol *node) const override
63     {
64         return node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName;
65     }
66 
67   private:
68     ImmutableString mSymbolName;
69 };
70 
71 class SymbolOccurrenceCounterByNameAndQualifier : public SymbolOccurrenceCounter
72 {
73   public:
SymbolOccurrenceCounterByNameAndQualifier(const ImmutableString & symbolName,TQualifier qualifier)74     SymbolOccurrenceCounterByNameAndQualifier(const ImmutableString &symbolName,
75                                               TQualifier qualifier)
76         : mSymbolName(symbolName), mSymbolQualifier(qualifier)
77     {}
78 
shouldCountSymbol(const TIntermSymbol * node) const79     bool shouldCountSymbol(const TIntermSymbol *node) const override
80     {
81         return node->variable().symbolType() != SymbolType::Empty &&
82                node->getName() == mSymbolName && node->getQualifier() == mSymbolQualifier;
83     }
84 
85   private:
86     ImmutableString mSymbolName;
87     TQualifier mSymbolQualifier;
88 };
89 
90 class OVRMultiview2VertexShaderTest : public ShaderCompileTreeTest
91 {
92   public:
OVRMultiview2VertexShaderTest()93     OVRMultiview2VertexShaderTest() {}
94 
95   protected:
getShaderType() const96     ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
getShaderSpec() const97     ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
initResources(ShBuiltInResources * resources)98     void initResources(ShBuiltInResources *resources) override
99     {
100         resources->OVR_multiview  = 1;
101         resources->OVR_multiview2 = 1;
102         resources->MaxViewsOVR    = 4;
103     }
104 };
105 
106 class OVRMultiview2FragmentShaderTest : public ShaderCompileTreeTest
107 {
108   public:
OVRMultiview2FragmentShaderTest()109     OVRMultiview2FragmentShaderTest() {}
110 
111   protected:
getShaderType() const112     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const113     ShShaderSpec getShaderSpec() const override { return SH_WEBGL3_SPEC; }
initResources(ShBuiltInResources * resources)114     void initResources(ShBuiltInResources *resources) override
115     {
116         resources->OVR_multiview  = 1;
117         resources->OVR_multiview2 = 1;
118         resources->MaxViewsOVR    = 4;
119     }
120 };
121 
122 class OVRMultiview2OutputCodeTest : public MatchOutputCodeTest
123 {
124   public:
OVRMultiview2OutputCodeTest(sh::GLenum shaderType)125     OVRMultiview2OutputCodeTest(sh::GLenum shaderType)
126         : MatchOutputCodeTest(shaderType, 0, SH_ESSL_OUTPUT)
127     {
128         addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
129 
130         getResources()->OVR_multiview  = 1;
131         getResources()->OVR_multiview2 = 1;
132         getResources()->MaxViewsOVR    = 4;
133     }
134 
requestHLSLOutput()135     void requestHLSLOutput()
136     {
137 #if defined(ANGLE_ENABLE_HLSL)
138         addOutputType(SH_HLSL_4_1_OUTPUT);
139 #endif
140     }
141 
foundInAllGLSLCode(const char * str)142     bool foundInAllGLSLCode(const char *str)
143     {
144         return foundInGLSLCode(str) && foundInESSLCode(str);
145     }
146 
foundInHLSLCode(const char * stringToFind) const147     bool foundInHLSLCode(const char *stringToFind) const
148     {
149 #if defined(ANGLE_ENABLE_HLSL)
150         return foundInCode(SH_HLSL_4_1_OUTPUT, stringToFind);
151 #else
152         return true;
153 #endif
154     }
155 };
156 
157 class OVRMultiview2VertexShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
158 {
159   public:
OVRMultiview2VertexShaderOutputCodeTest()160     OVRMultiview2VertexShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_VERTEX_SHADER) {}
161 };
162 
163 class OVRMultiview2FragmentShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
164 {
165   public:
OVRMultiview2FragmentShaderOutputCodeTest()166     OVRMultiview2FragmentShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_FRAGMENT_SHADER) {}
167 };
168 
169 class OVRMultiview2ComputeShaderOutputCodeTest : public OVRMultiview2OutputCodeTest
170 {
171   public:
OVRMultiview2ComputeShaderOutputCodeTest()172     OVRMultiview2ComputeShaderOutputCodeTest() : OVRMultiview2OutputCodeTest(GL_COMPUTE_SHADER) {}
173 };
174 
VariableOccursNTimes(TIntermBlock * root,const ImmutableString & varName,const TQualifier varQualifier,unsigned n)175 void VariableOccursNTimes(TIntermBlock *root,
176                           const ImmutableString &varName,
177                           const TQualifier varQualifier,
178                           unsigned n)
179 {
180     // Check that there are n occurrences of the variable with the given name and qualifier.
181     SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(varName, varQualifier);
182     root->traverse(&viewIDByNameAndQualifier);
183     EXPECT_EQ(n, viewIDByNameAndQualifier.getNumberOfOccurrences());
184 
185     // Check that there are n occurrences of the variable with the given name. By this we guarantee
186     // that there are no other occurrences of the variable with the same name but different
187     // qualifier.
188     SymbolOccurrenceCounterByName viewIDByName(varName);
189     root->traverse(&viewIDByName);
190     EXPECT_EQ(n, viewIDByName.getNumberOfOccurrences());
191 }
192 
193 // Invalid combination of non-matching num_views declarations.
TEST_F(OVRMultiview2VertexShaderTest,InvalidNumViewsMismatch)194 TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsMismatch)
195 {
196     const std::string &shaderString =
197         "#version 300 es\n"
198         "#extension GL_OVR_multiview2 : require\n"
199         "layout(num_views = 2) in;\n"
200         "layout(num_views = 1) in;\n"
201         "void main()\n"
202         "{\n"
203         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
204         "    gl_Position.yzw = vec3(0, 0, 1);\n"
205         "}\n";
206     if (compile(shaderString))
207     {
208         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
209     }
210 }
211 
212 // Invalid value zero for num_views.
TEST_F(OVRMultiview2VertexShaderTest,InvalidNumViewsZero)213 TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsZero)
214 {
215     const std::string &shaderString =
216         "#version 300 es\n"
217         "#extension GL_OVR_multiview2 : require\n"
218         "layout(num_views = 0) in;\n"
219         "void main()\n"
220         "{\n"
221         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
222         "    gl_Position.yzw = vec3(0, 0, 1);\n"
223         "}\n";
224     if (compile(shaderString))
225     {
226         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
227     }
228 }
229 
230 // Too large value for num_views.
TEST_F(OVRMultiview2VertexShaderTest,InvalidNumViewsGreaterThanMax)231 TEST_F(OVRMultiview2VertexShaderTest, InvalidNumViewsGreaterThanMax)
232 {
233     const std::string &shaderString =
234         "#version 300 es\n"
235         "#extension GL_OVR_multiview2 : require\n"
236         "layout(num_views = 5) in;\n"
237         "void main()\n"
238         "{\n"
239         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
240         "    gl_Position.yzw = vec3(0, 0, 1);\n"
241         "}\n";
242     if (compile(shaderString))
243     {
244         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
245     }
246 }
247 
248 // Valid use of gl_ViewID_OVR.
TEST_F(OVRMultiview2VertexShaderTest,ViewIDUsed)249 TEST_F(OVRMultiview2VertexShaderTest, ViewIDUsed)
250 {
251     const std::string &shaderString =
252         "#version 300 es\n"
253         "#extension GL_OVR_multiview2 : require\n"
254         "layout(num_views = 2) in;\n"
255         "layout(num_views = 2) in;  // Duplicated on purpose\n"
256         "in vec4 pos;\n"
257         "out float myOutput;\n"
258         "void main()\n"
259         "{\n"
260         "    if (gl_ViewID_OVR == 0u)\n"
261         "    {\n"
262         "        gl_Position = pos;\n"
263         "        myOutput = 1.0;\n"
264         "    }\n"
265         "    else\n"
266         "    {\n"
267         "        gl_Position = pos + vec4(1.0, 0.0, 0.0, 0.0);\n"
268         "        myOutput = 2.0;\n"
269         "    }\n"
270         "    gl_Position += (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
271         "}\n";
272     if (!compile(shaderString))
273     {
274         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
275     }
276 }
277 
278 // Read gl_FragCoord in a OVR_multiview2 fragment shader.
TEST_F(OVRMultiview2FragmentShaderTest,ReadOfFragCoord)279 TEST_F(OVRMultiview2FragmentShaderTest, ReadOfFragCoord)
280 {
281     const std::string &shaderString =
282         "#version 300 es\n"
283         "#extension GL_OVR_multiview2 : require\n"
284         "precision highp float;\n"
285         "out vec4 outColor;\n"
286         "void main()\n"
287         "{\n"
288         "    outColor = vec4(gl_FragCoord.xy, 0, 1);\n"
289         "}\n";
290     if (!compile(shaderString))
291     {
292         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
293     }
294 }
295 
296 // Read gl_ViewID_OVR in an OVR_multiview2 fragment shader.
TEST_F(OVRMultiview2FragmentShaderTest,ReadOfViewID)297 TEST_F(OVRMultiview2FragmentShaderTest, ReadOfViewID)
298 {
299     const std::string &shaderString =
300         "#version 300 es\n"
301         "#extension GL_OVR_multiview2 : require\n"
302         "precision highp float;\n"
303         "out vec4 outColor;\n"
304         "void main()\n"
305         "{\n"
306         "    outColor = vec4(gl_ViewID_OVR, 0, 0, 1);\n"
307         "}\n";
308     if (!compile(shaderString))
309     {
310         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
311     }
312 }
313 
314 // Correct use of GL_OVR_multiview2 macro.
TEST_F(OVRMultiview2VertexShaderTest,UseOfExtensionMacro)315 TEST_F(OVRMultiview2VertexShaderTest, UseOfExtensionMacro)
316 {
317     const std::string &shaderString =
318         "#version 300 es\n"
319         "#ifdef GL_OVR_multiview2\n"
320         "#if (GL_OVR_multiview2 == 1)\n"
321         "void main()\n"
322         "{\n"
323         "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
324         "}\n"
325         "#endif\n"
326         "#endif\n";
327     if (!compile(shaderString))
328     {
329         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
330     }
331 }
332 
333 // Test that gl_ViewID_OVR can't be used as an l-value.
TEST_F(OVRMultiview2VertexShaderTest,ViewIdAsLValue)334 TEST_F(OVRMultiview2VertexShaderTest, ViewIdAsLValue)
335 {
336     const std::string &shaderString =
337         "#version 300 es\n"
338         "#extension GL_OVR_multiview2 : require\n"
339         "layout(num_views = 2) in;\n"
340         "void foo(out uint u)\n"
341         "{\n"
342         "    u = 3u;\n"
343         "}\n"
344         "void main()\n"
345         "{\n"
346         "    foo(gl_ViewID_OVR);\n"
347         "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
348         "}\n";
349     if (compile(shaderString))
350     {
351         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
352     }
353 }
354 
355 // Test that compiling an ESSL 1.00 shader with multiview support fails.
TEST_F(OVRMultiview2VertexShaderTest,ESSL1Shader)356 TEST_F(OVRMultiview2VertexShaderTest, ESSL1Shader)
357 {
358     const std::string &shaderString =
359         "#extension GL_OVR_multiview2 : require\n"
360         "layout(num_views = 2) in;\n"
361         "void main()\n"
362         "{\n"
363         "    if (gl_ViewID_OVR == 0)\n"
364         "    {\n"
365         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
366         "    }\n"
367         "    else\n"
368         "    {\n"
369         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
370         "    }\n"
371         "}\n";
372     if (compile(shaderString))
373     {
374         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
375     }
376 }
377 
378 // Test that compiling an ESSL 1.00 shader with an unsupported global layout qualifier fails.
TEST_F(OVRMultiview2VertexShaderTest,ESSL1ShaderUnsupportedGlobalLayoutQualifier)379 TEST_F(OVRMultiview2VertexShaderTest, ESSL1ShaderUnsupportedGlobalLayoutQualifier)
380 {
381     const std::string &shaderString =
382         "#extension GL_OVR_multiview2 : require\n"
383         "layout(num_views = 2) in;\n"
384         "layout(std140) uniform;\n"
385         "void main()\n"
386         "{\n"
387         "    if (gl_ViewID_OVR == 0)\n"
388         "    {\n"
389         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
390         "    }\n"
391         "    else\n"
392         "    {\n"
393         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
394         "    }\n"
395         "}\n";
396     if (compile(shaderString))
397     {
398         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
399     }
400 }
401 
402 // Test that compiling an ESSL 1.00 vertex shader with an unsupported input storage qualifier fails.
TEST_F(OVRMultiview2VertexShaderTest,ESSL1ShaderUnsupportedInputStorageQualifier)403 TEST_F(OVRMultiview2VertexShaderTest, ESSL1ShaderUnsupportedInputStorageQualifier)
404 {
405     const std::string &shaderString =
406         "#extension GL_OVR_multiview2 : require\n"
407         "layout(num_views = 2) in;\n"
408         "in vec4 pos;\n"
409         "void main()\n"
410         "{\n"
411         "    if (gl_ViewID_OVR == 0)\n"
412         "    {\n"
413         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
414         "    }\n"
415         "    else\n"
416         "    {\n"
417         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
418         "    }\n"
419         "}\n";
420     if (compile(shaderString))
421     {
422         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
423     }
424 }
425 
426 // Test that compiling an ESSL 1.00 fragment shader with an unsupported input storage qualifier
427 // fails.
TEST_F(OVRMultiview2FragmentShaderTest,ESSL1ShaderUnsupportedInStorageQualifier)428 TEST_F(OVRMultiview2FragmentShaderTest, ESSL1ShaderUnsupportedInStorageQualifier)
429 {
430     const std::string &shaderString =
431         "#extension GL_OVR_multiview2 : require\n"
432         "precision highp float;\n"
433         "in vec4 color;\n"
434         "void main()\n"
435         "{\n"
436         "    if (gl_ViewID_OVR == 0)\n"
437         "    {\n"
438         "        gl_FragColor = color;\n"
439         "    }\n"
440         "    else\n"
441         "    {\n"
442         "        gl_FragColor = color + vec4(1.0, 0.0, 0.0, 1.0);\n"
443         "    }\n"
444         "}\n";
445     if (compile(shaderString))
446     {
447         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
448     }
449 }
450 
451 // Test that gl_InstanceID gets correctly replaced by InstanceID. gl_InstanceID should only be used
452 // twice: once to initialize ViewID_OVR and once for InstanceID. The number of occurrences of
453 // InstanceID in the AST should be the sum of two and the number of occurrences of gl_InstanceID
454 // before any renaming.
TEST_F(OVRMultiview2VertexShaderTest,GLInstanceIDIsRenamed)455 TEST_F(OVRMultiview2VertexShaderTest, GLInstanceIDIsRenamed)
456 {
457     const std::string &shaderString =
458         "#version 300 es\n"
459         "#extension GL_OVR_multiview2 : require\n"
460         "layout(num_views = 2) in;\n"
461         "flat out int myInstance;\n"
462         "out float myInstanceF;\n"
463         "out float myInstanceF2;\n"
464         "void main()\n"
465         "{\n"
466         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
467         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
468         "   myInstance = gl_InstanceID;\n"
469         "   myInstanceF = float(gl_InstanceID) + .5;\n"
470         "   myInstanceF2 = float(gl_InstanceID) + .1;\n"
471         "}\n";
472     mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
473     compileAssumeSuccess(shaderString);
474 
475     SymbolOccurrenceCounterByName glInstanceIDByName(ImmutableString("gl_InstanceID"));
476     mASTRoot->traverse(&glInstanceIDByName);
477     EXPECT_EQ(2u, glInstanceIDByName.getNumberOfOccurrences());
478 
479     SymbolOccurrenceCounterByQualifier glInstanceIDByQualifier(EvqInstanceID);
480     mASTRoot->traverse(&glInstanceIDByQualifier);
481     EXPECT_EQ(2u, glInstanceIDByQualifier.getNumberOfOccurrences());
482 
483     SymbolOccurrenceCounterByName instanceIDByName(ImmutableString("InstanceID"));
484     mASTRoot->traverse(&instanceIDByName);
485     EXPECT_EQ(5u, instanceIDByName.getNumberOfOccurrences());
486 }
487 
488 // Test that gl_ViewID_OVR gets correctly replaced by ViewID_OVR. gl_ViewID_OVR should not be found
489 // by either name or qualifier. The number of occurrences of ViewID_OVR in the AST should be the sum
490 // of two and the number of occurrences of gl_ViewID_OVR before any renaming.
TEST_F(OVRMultiview2VertexShaderTest,GLViewIDIsRenamed)491 TEST_F(OVRMultiview2VertexShaderTest, GLViewIDIsRenamed)
492 {
493     const std::string &shaderString =
494         "#version 300 es\n"
495         "#extension GL_OVR_multiview2 : require\n"
496         "layout(num_views = 2) in;\n"
497         "flat out uint a;\n"
498         "void main()\n"
499         "{\n"
500         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
501         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
502         "   a = gl_ViewID_OVR == 0u ? (gl_ViewID_OVR+2u) : gl_ViewID_OVR;\n"
503         "}\n";
504     mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
505     compileAssumeSuccess(shaderString);
506 
507     SymbolOccurrenceCounterByName glViewIDOVRByName(ImmutableString("gl_ViewID_OVR"));
508     mASTRoot->traverse(&glViewIDOVRByName);
509     EXPECT_EQ(0u, glViewIDOVRByName.getNumberOfOccurrences());
510 
511     SymbolOccurrenceCounterByQualifier glViewIDOVRByQualifier(EvqViewIDOVR);
512     mASTRoot->traverse(&glViewIDOVRByQualifier);
513     EXPECT_EQ(0u, glViewIDOVRByQualifier.getNumberOfOccurrences());
514 
515     SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(
516         ImmutableString("ViewID_OVR"), EvqFlatOut);
517     mASTRoot->traverse(&viewIDByNameAndQualifier);
518     EXPECT_EQ(6u, viewIDByNameAndQualifier.getNumberOfOccurrences());
519 }
520 
521 // The test checks that ViewID_OVR and InstanceID have the correct initializers based on the
522 // number of views.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,ViewIDAndInstanceIDHaveCorrectValues)523 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectValues)
524 {
525     const std::string &shaderString =
526         "#version 300 es\n"
527         "#extension GL_OVR_multiview2 : require\n"
528         "layout(num_views = 3) in;\n"
529         "flat out int myInstance;\n"
530         "void main()\n"
531         "{\n"
532         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
533         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
534         "   myInstance = gl_InstanceID;\n"
535         "}\n";
536     requestHLSLOutput();
537     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
538 
539     EXPECT_TRUE(foundInAllGLSLCode("ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
540     EXPECT_TRUE(foundInAllGLSLCode("InstanceID = int((uint(gl_InstanceID) / 3u))"));
541 
542     EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uint_ctor(gl_InstanceID) % 3)"));
543 #if defined(ANGLE_ENABLE_HLSL)
544     EXPECT_FALSE(foundInHLSLCode("_ViewID_OVR = (uint_ctor(gl_InstanceID) % 3)"));
545 #endif
546     EXPECT_TRUE(foundInHLSLCode("InstanceID = int_ctor((uint_ctor(gl_InstanceID) / 3))"));
547 }
548 
549 // The test checks that the directive enabling GL_OVR_multiview2 is not outputted if the extension
550 // is emulated.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,StrippedOVRMultiviewDirective)551 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, StrippedOVRMultiviewDirective)
552 {
553     const std::string &shaderString =
554         "#version 300 es\n"
555         "#extension GL_OVR_multiview2 : require\n"
556         "layout(num_views = 3) in;\n"
557         "void main()\n"
558         "{\n"
559         "}\n";
560     // The directive must not be present if any of the multiview emulation options are set.
561     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
562     EXPECT_FALSE(foundInESSLCode("GL_OVR_multiview2"));
563     EXPECT_FALSE(foundInGLSLCode("GL_OVR_multiview2"));
564 
565     // The directive should be outputted from the ESSL translator with none of the options being
566     // set.
567     compile(shaderString);
568     EXPECT_TRUE(foundInESSLCode("GL_OVR_multiview2"));
569 }
570 
571 // Test that ViewID_OVR is declared as a flat input variable in an ESSL 3.00 fragment shader.
TEST_F(OVRMultiview2FragmentShaderTest,ViewIDDeclaredAsFlatInput)572 TEST_F(OVRMultiview2FragmentShaderTest, ViewIDDeclaredAsFlatInput)
573 {
574     const std::string &shaderString =
575         "#version 300 es\n"
576         "#extension GL_OVR_multiview2 : require\n"
577         "void main()\n"
578         "{\n"
579         "}\n";
580     mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
581     compileAssumeSuccess(shaderString);
582     VariableOccursNTimes(mASTRoot, ImmutableString("ViewID_OVR"), EvqFlatIn, 1u);
583 }
584 
585 // Test that GL_OVR_multiview is not defined by the preprocessor for WebGL spec shader;
586 // Test that GL_OVR_multiview2 is defined by the preprocessor for WebGL spec shader.
TEST_F(OVRMultiview2FragmentShaderTest,PreprocessorOutput)587 TEST_F(OVRMultiview2FragmentShaderTest, PreprocessorOutput)
588 {
589     const std::string &shaderString =
590         "#version 300 es\n"
591         "#extension GL_OVR_multiview2 : require\n"
592         "#ifdef GL_OVR_multiview\n"
593         "    #error legacy GL_OVR_multiview support must be forbidden\n"
594         "#endif\n"
595         "#ifndef GL_OVR_multiview2\n"
596         "    #error GL_OVR_multiview2 support must be enabled\n"
597         "#endif\n"
598         "void main()\n"
599         "{\n"
600         "}\n";
601     compileAssumeSuccess(shaderString);
602 }
603 
604 // Test that ViewID_OVR is declared as a flat output variable in an ESSL 1.00 vertex shader.
TEST_F(OVRMultiview2VertexShaderTest,ViewIDDeclaredAsFlatOutput)605 TEST_F(OVRMultiview2VertexShaderTest, ViewIDDeclaredAsFlatOutput)
606 {
607     const std::string &shaderString =
608         "#extension GL_OVR_multiview2 : require\n"
609         "void main()\n"
610         "{\n"
611         "}\n";
612     mExtraCompileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
613     compileAssumeSuccess(shaderString);
614     VariableOccursNTimes(mASTRoot, ImmutableString("ViewID_OVR"), EvqFlatOut, 2u);
615 }
616 
617 // Test that GL_OVR_multiview is not defined by the preprocessor for WebGL spec shader;
618 // Test that GL_OVR_multiview2 is defined by the preprocessor for WebGL spec shader.
TEST_F(OVRMultiview2VertexShaderTest,PreprocessorOutput)619 TEST_F(OVRMultiview2VertexShaderTest, PreprocessorOutput)
620 {
621     const std::string &shaderString =
622         "#version 300 es\n"
623         "#extension GL_OVR_multiview2 : require\n"
624         "#ifdef GL_OVR_multiview\n"
625         "    #error legacy GL_OVR_multiview support must be forbidden\n"
626         "#endif\n"
627         "#ifndef GL_OVR_multiview2\n"
628         "    #error GL_OVR_multiview2 support must be enabled\n"
629         "#endif\n"
630         "void main()\n"
631         "{\n"
632         "}\n";
633     compileAssumeSuccess(shaderString);
634 }
635 
636 // The test checks that the GL_NV_viewport_array2 extension is emitted in a vertex shader if the
637 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,ViewportArray2IsEmitted)638 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewportArray2IsEmitted)
639 {
640     const std::string &shaderString =
641         "#version 300 es\n"
642         "#extension GL_OVR_multiview2 : require\n"
643         "layout(num_views = 3) in;\n"
644         "void main()\n"
645         "{\n"
646         "}\n";
647     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
648                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
649     EXPECT_TRUE(foundInAllGLSLCode("#extension GL_NV_viewport_array2 : require"));
650 }
651 
652 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a vertex shader if the
653 // OVR_multiview2 extension is not requested in the shader source even if the
654 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,ViewportArray2IsNotEmitted)655 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, ViewportArray2IsNotEmitted)
656 {
657     const std::string &shaderString =
658         "#version 300 es\n"
659         "void main()\n"
660         "{\n"
661         "}\n";
662     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
663                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
664     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
665     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
666 }
667 
668 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a fragment shader if
669 // the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
TEST_F(OVRMultiview2FragmentShaderOutputCodeTest,ViewportArray2IsNotEmitted)670 TEST_F(OVRMultiview2FragmentShaderOutputCodeTest, ViewportArray2IsNotEmitted)
671 {
672     const std::string &shaderString =
673         "#version 300 es\n"
674         "#extension GL_OVR_multiview2 : require\n"
675         "void main()\n"
676         "{\n"
677         "}\n";
678     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
679                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
680     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
681     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
682 }
683 
684 // The test checks if OVR_multiview2 is emitted only once and no other
685 // multiview extensions are emitted.
TEST_F(OVRMultiview2FragmentShaderOutputCodeTest,NativeOvrMultiview2Output)686 TEST_F(OVRMultiview2FragmentShaderOutputCodeTest, NativeOvrMultiview2Output)
687 {
688     const std::string &shaderString =
689         "#version 300 es\n"
690         "#extension GL_OVR_multiview2 : require\n"
691         "void main()\n"
692         "{\n"
693         "}\n";
694     compile(shaderString);
695     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
696     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
697 
698     EXPECT_TRUE(foundInESSLCode("#extension GL_OVR_multiview2"));
699     EXPECT_TRUE(foundInGLSLCode("#extension GL_OVR_multiview2"));
700 
701     // no double extension
702     std::vector<const char *> notExpectedStrings1 = {"#extension GL_OVR_multiview",
703                                                      "#extension GL_OVR_multiview"};
704     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings1));
705     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings1));
706 }
707 
708 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a compute shader if
709 // the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set.
TEST_F(OVRMultiview2ComputeShaderOutputCodeTest,ViewportArray2IsNotEmitted)710 TEST_F(OVRMultiview2ComputeShaderOutputCodeTest, ViewportArray2IsNotEmitted)
711 {
712     const std::string &shaderString =
713         R"(#version 310 es
714         #extension GL_OVR_multiview2 : require
715         void main()
716         {
717         })";
718     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
719                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
720     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
721     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
722 }
723 
724 // The test checks that the viewport index is selected after the initialization of ViewID_OVR for
725 // GLSL and ESSL ouputs.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,GlViewportIndexIsSet)726 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, GlViewportIndexIsSet)
727 {
728     const std::string &shaderString =
729         "#version 300 es\n"
730         "#extension GL_OVR_multiview2 : require\n"
731         "layout(num_views = 3) in;\n"
732         "void main()\n"
733         "{\n"
734         "}\n";
735     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
736                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
737 
738     std::vector<const char *> expectedStrings = {"ViewID_OVR = (uint(gl_InstanceID) % 3u)",
739                                                  "gl_ViewportIndex = int(ViewID_OVR)"};
740     EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
741     EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
742 }
743 
744 // The test checks that the layer is selected after the initialization of ViewID_OVR for
745 // GLSL and ESSL ouputs.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,GlLayerIsSet)746 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, GlLayerIsSet)
747 {
748     const std::string &shaderString =
749         "#version 300 es\n"
750         "#extension GL_OVR_multiview2 : require\n"
751         "layout(num_views = 3) in;\n"
752         "void main()\n"
753         "{\n"
754         "}\n";
755     compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
756                               SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
757 
758     std::vector<const char *> expectedStrings = {
759         "ViewID_OVR = (uint(gl_InstanceID) % 3u)",
760         "gl_Layer = (int(ViewID_OVR) + multiviewBaseViewLayerIndex)"};
761     EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
762     EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
763 }
764 
765 // Test that the OVR_multiview2 without emulation emits OVR_multiview2 output.
766 // It also tests that the GL_OVR_multiview2 is emitted only once and no other
767 // multiview extensions are emitted.
TEST_F(OVRMultiview2VertexShaderOutputCodeTest,NativeOvrMultiview2Output)768 TEST_F(OVRMultiview2VertexShaderOutputCodeTest, NativeOvrMultiview2Output)
769 {
770     const std::string &shaderString =
771         "#version 300 es\n"
772         "#extension GL_OVR_multiview2 : require\n"
773         "layout(num_views = 3) in;\n"
774         "void main()\n"
775         "{\n"
776         "}\n";
777     compile(shaderString);
778 
779     std::vector<const char *> expectedStrings = {"#extension GL_OVR_multiview2",
780                                                  "layout(num_views"};
781     EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
782     EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
783 
784     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
785     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
786 
787     EXPECT_FALSE(foundInGLSLCode("gl_ViewportIndex"));
788     EXPECT_FALSE(foundInESSLCode("gl_ViewportIndex"));
789 
790     // no double extension
791     std::vector<const char *> notExpectedStrings1 = {"#extension GL_OVR_multiview",
792                                                      "#extension GL_OVR_multiview"};
793     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings1));
794     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings1));
795 
796     // no double num_views
797     std::vector<const char *> notExpectedStrings2 = {"layout(num_views", "layout(num_views"};
798     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings2));
799     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings2));
800 }
801 
802 }  // namespace
803