xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/OVR_multiview_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2019 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_multiview_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 OVRMultiviewVertexShaderTest : public ShaderCompileTreeTest
91 {
92   public:
OVRMultiviewVertexShaderTest()93     OVRMultiviewVertexShaderTest() {}
94 
95   protected:
getShaderType() const96     ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
getShaderSpec() const97     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
initResources(ShBuiltInResources * resources)98     void initResources(ShBuiltInResources *resources) override
99     {
100         resources->OVR_multiview = 1;
101         resources->MaxViewsOVR   = 4;
102     }
103 };
104 
105 class OVRMultiviewFragmentShaderTest : public ShaderCompileTreeTest
106 {
107   public:
OVRMultiviewFragmentShaderTest()108     OVRMultiviewFragmentShaderTest() {}
109 
110   protected:
getShaderType() const111     ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
getShaderSpec() const112     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
initResources(ShBuiltInResources * resources)113     void initResources(ShBuiltInResources *resources) override
114     {
115         resources->OVR_multiview = 1;
116         resources->MaxViewsOVR   = 4;
117     }
118 };
119 
120 class OVRMultiviewOutputCodeTest : public MatchOutputCodeTest
121 {
122   public:
OVRMultiviewOutputCodeTest(sh::GLenum shaderType)123     OVRMultiviewOutputCodeTest(sh::GLenum shaderType)
124         : MatchOutputCodeTest(shaderType, SH_ESSL_OUTPUT), mMultiviewCompileOptions{}
125     {
126         addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
127 
128         getResources()->OVR_multiview = 1;
129         getResources()->MaxViewsOVR   = 4;
130 
131         mMultiviewCompileOptions.initializeBuiltinsForInstancedMultiview = true;
132         mMultiviewCompileOptions.selectViewInNvGLSLVertexShader          = true;
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   protected:
157     ShCompileOptions mMultiviewCompileOptions;
158 };
159 
160 class OVRMultiviewVertexShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
161 {
162   public:
OVRMultiviewVertexShaderOutputCodeTest()163     OVRMultiviewVertexShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_VERTEX_SHADER) {}
164 };
165 
166 class OVRMultiviewFragmentShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
167 {
168   public:
OVRMultiviewFragmentShaderOutputCodeTest()169     OVRMultiviewFragmentShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_FRAGMENT_SHADER) {}
170 };
171 
172 class OVRMultiviewComputeShaderOutputCodeTest : public OVRMultiviewOutputCodeTest
173 {
174   public:
OVRMultiviewComputeShaderOutputCodeTest()175     OVRMultiviewComputeShaderOutputCodeTest() : OVRMultiviewOutputCodeTest(GL_COMPUTE_SHADER) {}
176 };
177 
VariableOccursNTimes(TIntermBlock * root,const ImmutableString & varName,const TQualifier varQualifier,unsigned n)178 void VariableOccursNTimes(TIntermBlock *root,
179                           const ImmutableString &varName,
180                           const TQualifier varQualifier,
181                           unsigned n)
182 {
183     // Check that there are n occurrences of the variable with the given name and qualifier.
184     SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(varName, varQualifier);
185     root->traverse(&viewIDByNameAndQualifier);
186     EXPECT_EQ(n, viewIDByNameAndQualifier.getNumberOfOccurrences());
187 
188     // Check that there are n occurrences of the variable with the given name. By this we guarantee
189     // that there are no other occurrences of the variable with the same name but different
190     // qualifier.
191     SymbolOccurrenceCounterByName viewIDByName(varName);
192     root->traverse(&viewIDByName);
193     EXPECT_EQ(n, viewIDByName.getNumberOfOccurrences());
194 }
195 
196 // Unsupported GL_OVR_multiview extension directive (GL_OVR_multiview spec only exposes
197 // GL_OVR_multiview).
TEST_F(OVRMultiviewVertexShaderTest,InvalidMultiview)198 TEST_F(OVRMultiviewVertexShaderTest, InvalidMultiview)
199 {
200     const std::string &shaderString =
201         "#version 300 es\n"
202         "#extension GL_OVR_multiview2 : require\n"
203         "layout(num_views = 2) in;\n"
204         "void main()\n"
205         "{\n"
206         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
207         "    gl_Position.yzw = vec3(0, 0, 1);\n"
208         "}\n";
209     if (compile(shaderString))
210     {
211         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
212     }
213 }
214 
215 // Invalid combination of non-matching num_views declarations.
TEST_F(OVRMultiviewVertexShaderTest,InvalidNumViewsMismatch)216 TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsMismatch)
217 {
218     const std::string &shaderString =
219         "#version 300 es\n"
220         "#extension GL_OVR_multiview : require\n"
221         "layout(num_views = 2) in;\n"
222         "layout(num_views = 1) in;\n"
223         "void main()\n"
224         "{\n"
225         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
226         "    gl_Position.yzw = vec3(0, 0, 1);\n"
227         "}\n";
228     if (compile(shaderString))
229     {
230         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
231     }
232 }
233 
234 // Invalid value zero for num_views.
TEST_F(OVRMultiviewVertexShaderTest,InvalidNumViewsZero)235 TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsZero)
236 {
237     const std::string &shaderString =
238         "#version 300 es\n"
239         "#extension GL_OVR_multiview : require\n"
240         "layout(num_views = 0) in;\n"
241         "void main()\n"
242         "{\n"
243         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
244         "    gl_Position.yzw = vec3(0, 0, 1);\n"
245         "}\n";
246     if (compile(shaderString))
247     {
248         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
249     }
250 }
251 
252 // Too large value for num_views.
TEST_F(OVRMultiviewVertexShaderTest,InvalidNumViewsGreaterThanMax)253 TEST_F(OVRMultiviewVertexShaderTest, InvalidNumViewsGreaterThanMax)
254 {
255     const std::string &shaderString =
256         "#version 300 es\n"
257         "#extension GL_OVR_multiview : require\n"
258         "layout(num_views = 5) in;\n"
259         "void main()\n"
260         "{\n"
261         "    gl_Position.x = (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
262         "    gl_Position.yzw = vec3(0, 0, 1);\n"
263         "}\n";
264     if (compile(shaderString))
265     {
266         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
267     }
268 }
269 
270 // Test that GL_OVR_multiview cannot be used in an ESSL 1.00 vertex shader.
TEST_F(OVRMultiviewVertexShaderTest,InvalidShaderVersion)271 TEST_F(OVRMultiviewVertexShaderTest, InvalidShaderVersion)
272 {
273     const std::string &shaderString =
274         "#extension GL_OVR_multiview : require\n"
275         "void main()\n"
276         "{\n"
277         "}\n";
278     if (compile(shaderString))
279     {
280         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
281     }
282 }
283 
284 // Valid use of gl_ViewID_OVR.
TEST_F(OVRMultiviewVertexShaderTest,ViewIDUsed)285 TEST_F(OVRMultiviewVertexShaderTest, ViewIDUsed)
286 {
287     const std::string &shaderString =
288         "#version 300 es\n"
289         "#extension GL_OVR_multiview : require\n"
290         "layout(num_views = 2) in;\n"
291         "layout(num_views = 2) in;  // Duplicated on purpose\n"
292         "in vec4 pos;\n"
293         "out float myOutput;\n"
294         "void main()\n"
295         "{\n"
296         "    if (gl_ViewID_OVR == 0u)\n"
297         "    {\n"
298         "        gl_Position = pos;\n"
299         "        myOutput = 1.0;\n"
300         "    }\n"
301         "    else\n"
302         "    {\n"
303         "        gl_Position = pos + vec4(1.0, 0.0, 0.0, 0.0);\n"
304         "        myOutput = 2.0;\n"
305         "    }\n"
306         "    gl_Position += (gl_ViewID_OVR == 0u) ? 1.0 : 0.0;\n"
307         "}\n";
308     if (!compile(shaderString))
309     {
310         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
311     }
312 }
313 
314 // Read gl_FragCoord in a OVR_multiview2 fragment shader.
TEST_F(OVRMultiviewFragmentShaderTest,ReadOfFragCoord)315 TEST_F(OVRMultiviewFragmentShaderTest, ReadOfFragCoord)
316 {
317     const std::string &shaderString =
318         "#version 300 es\n"
319         "#extension GL_OVR_multiview : require\n"
320         "precision highp float;\n"
321         "out vec4 outColor;\n"
322         "void main()\n"
323         "{\n"
324         "    outColor = vec4(gl_FragCoord.xy, 0, 1);\n"
325         "}\n";
326     if (!compile(shaderString))
327     {
328         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
329     }
330 }
331 
332 // Read gl_ViewID_OVR in an OVR_multiview2 fragment shader.
TEST_F(OVRMultiviewFragmentShaderTest,ReadOfViewID)333 TEST_F(OVRMultiviewFragmentShaderTest, ReadOfViewID)
334 {
335     const std::string &shaderString =
336         "#version 300 es\n"
337         "#extension GL_OVR_multiview : require\n"
338         "precision highp float;\n"
339         "out vec4 outColor;\n"
340         "void main()\n"
341         "{\n"
342         "    outColor = vec4(gl_ViewID_OVR, 0, 0, 1);\n"
343         "}\n";
344     if (!compile(shaderString))
345     {
346         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
347     }
348 }
349 
350 // Correct use of GL_OVR_multiview macro.
TEST_F(OVRMultiviewVertexShaderTest,UseOfExtensionMacro)351 TEST_F(OVRMultiviewVertexShaderTest, UseOfExtensionMacro)
352 {
353     const std::string &shaderString =
354         "#version 300 es\n"
355         "#ifdef GL_OVR_multiview\n"
356         "#if (GL_OVR_multiview == 1)\n"
357         "void main()\n"
358         "{\n"
359         "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
360         "}\n"
361         "#endif\n"
362         "#endif\n";
363     if (!compile(shaderString))
364     {
365         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
366     }
367 }
368 
369 // Test that gl_ViewID_OVR can't be used as an l-value.
TEST_F(OVRMultiviewVertexShaderTest,ViewIdAsLValue)370 TEST_F(OVRMultiviewVertexShaderTest, ViewIdAsLValue)
371 {
372     const std::string &shaderString =
373         "#version 300 es\n"
374         "#extension GL_OVR_multiview : require\n"
375         "layout(num_views = 2) in;\n"
376         "void foo(out uint u)\n"
377         "{\n"
378         "    u = 3u;\n"
379         "}\n"
380         "void main()\n"
381         "{\n"
382         "    foo(gl_ViewID_OVR);\n"
383         "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
384         "}\n";
385     if (compile(shaderString))
386     {
387         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
388     }
389 }
390 
391 // Test that compiling an ESSL 1.00 shader with multiview support fails.
TEST_F(OVRMultiviewVertexShaderTest,ESSL1Shader)392 TEST_F(OVRMultiviewVertexShaderTest, ESSL1Shader)
393 {
394     const std::string &shaderString =
395         "#extension GL_OVR_multiview : require\n"
396         "layout(num_views = 2) in;\n"
397         "void main()\n"
398         "{\n"
399         "    if (gl_ViewID_OVR == 0)\n"
400         "    {\n"
401         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
402         "    }\n"
403         "    else\n"
404         "    {\n"
405         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
406         "    }\n"
407         "}\n";
408     if (compile(shaderString))
409     {
410         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
411     }
412 }
413 
414 // Test that compiling an ESSL 1.00 shader with an unsupported global layout qualifier fails.
TEST_F(OVRMultiviewVertexShaderTest,ESSL1ShaderUnsupportedGlobalLayoutQualifier)415 TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedGlobalLayoutQualifier)
416 {
417     const std::string &shaderString =
418         "#extension GL_OVR_multiview : require\n"
419         "layout(num_views = 2) in;\n"
420         "layout(std140) uniform;\n"
421         "void main()\n"
422         "{\n"
423         "    if (gl_ViewID_OVR == 0)\n"
424         "    {\n"
425         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
426         "    }\n"
427         "    else\n"
428         "    {\n"
429         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
430         "    }\n"
431         "}\n";
432     if (compile(shaderString))
433     {
434         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
435     }
436 }
437 
438 // Test that compiling an ESSL 1.00 vertex shader with an unsupported input storage qualifier fails.
TEST_F(OVRMultiviewVertexShaderTest,ESSL1ShaderUnsupportedInputStorageQualifier)439 TEST_F(OVRMultiviewVertexShaderTest, ESSL1ShaderUnsupportedInputStorageQualifier)
440 {
441     const std::string &shaderString =
442         "#extension GL_OVR_multiview : require\n"
443         "layout(num_views = 2) in;\n"
444         "in vec4 pos;\n"
445         "void main()\n"
446         "{\n"
447         "    if (gl_ViewID_OVR == 0)\n"
448         "    {\n"
449         "        gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
450         "    }\n"
451         "    else\n"
452         "    {\n"
453         "        gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
454         "    }\n"
455         "}\n";
456     if (compile(shaderString))
457     {
458         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
459     }
460 }
461 
462 // Test that compiling an ESSL 1.00 fragment shader with an unsupported input storage qualifier
463 // fails.
TEST_F(OVRMultiviewFragmentShaderTest,ESSL1ShaderUnsupportedInStorageQualifier)464 TEST_F(OVRMultiviewFragmentShaderTest, ESSL1ShaderUnsupportedInStorageQualifier)
465 {
466     const std::string &shaderString =
467         "#extension GL_OVR_multiview : require\n"
468         "precision highp float;\n"
469         "in vec4 color;\n"
470         "void main()\n"
471         "{\n"
472         "    if (gl_ViewID_OVR == 0)\n"
473         "    {\n"
474         "        gl_FragColor = color;\n"
475         "    }\n"
476         "    else\n"
477         "    {\n"
478         "        gl_FragColor = color + vec4(1.0, 0.0, 0.0, 1.0);\n"
479         "    }\n"
480         "}\n";
481     if (compile(shaderString))
482     {
483         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
484     }
485 }
486 
487 // Test that gl_InstanceID gets correctly replaced by InstanceID. gl_InstanceID should only be used
488 // twice: once to initialize ViewID_OVR and once for InstanceID. The number of occurrences of
489 // InstanceID in the AST should be the sum of two and the number of occurrences of gl_InstanceID
490 // before any renaming.
TEST_F(OVRMultiviewVertexShaderTest,GLInstanceIDIsRenamed)491 TEST_F(OVRMultiviewVertexShaderTest, GLInstanceIDIsRenamed)
492 {
493     const std::string &shaderString =
494         "#version 300 es\n"
495         "#extension GL_OVR_multiview : require\n"
496         "layout(num_views = 2) in;\n"
497         "flat out int myInstance;\n"
498         "out float myInstanceF;\n"
499         "out float myInstanceF2;\n"
500         "void main()\n"
501         "{\n"
502         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
503         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
504         "   myInstance = gl_InstanceID;\n"
505         "   myInstanceF = float(gl_InstanceID) + .5;\n"
506         "   myInstanceF2 = float(gl_InstanceID) + .1;\n"
507         "}\n";
508     mCompileOptions.initializeBuiltinsForInstancedMultiview = true;
509     compileAssumeSuccess(shaderString);
510 
511     SymbolOccurrenceCounterByName glInstanceIDByName(ImmutableString("gl_InstanceID"));
512     mASTRoot->traverse(&glInstanceIDByName);
513     EXPECT_EQ(2u, glInstanceIDByName.getNumberOfOccurrences());
514 
515     SymbolOccurrenceCounterByQualifier glInstanceIDByQualifier(EvqInstanceID);
516     mASTRoot->traverse(&glInstanceIDByQualifier);
517     EXPECT_EQ(2u, glInstanceIDByQualifier.getNumberOfOccurrences());
518 
519     SymbolOccurrenceCounterByName instanceIDByName(ImmutableString("InstanceID"));
520     mASTRoot->traverse(&instanceIDByName);
521     EXPECT_EQ(5u, instanceIDByName.getNumberOfOccurrences());
522 }
523 
524 // Test that gl_ViewID_OVR gets correctly replaced by ViewID_OVR. gl_ViewID_OVR should not be found
525 // by the name. The number of occurrences of ViewID_OVR in the AST should be the sum
526 // of two and the number of occurrences of gl_ViewID_OVR before any renaming.
TEST_F(OVRMultiviewVertexShaderTest,GLViewIDIsRenamed)527 TEST_F(OVRMultiviewVertexShaderTest, GLViewIDIsRenamed)
528 {
529     const std::string &shaderString =
530         "#version 300 es\n"
531         "#extension GL_OVR_multiview : require\n"
532         "layout(num_views = 2) in;\n"
533         "flat out uint a;\n"
534         "void main()\n"
535         "{\n"
536         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
537         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
538         "   a = gl_ViewID_OVR == 0u ? (gl_ViewID_OVR+2u) : gl_ViewID_OVR;\n"
539         "}\n";
540     mCompileOptions.initializeBuiltinsForInstancedMultiview = true;
541     compileAssumeSuccess(shaderString);
542 
543     SymbolOccurrenceCounterByName glViewIDOVRByName(ImmutableString("gl_ViewID_OVR"));
544     mASTRoot->traverse(&glViewIDOVRByName);
545     EXPECT_EQ(0u, glViewIDOVRByName.getNumberOfOccurrences());
546 
547     SymbolOccurrenceCounterByNameAndQualifier viewIDByNameAndQualifier(
548         ImmutableString("ViewID_OVR"), EvqViewIDOVR);
549     mASTRoot->traverse(&viewIDByNameAndQualifier);
550     EXPECT_EQ(6u, viewIDByNameAndQualifier.getNumberOfOccurrences());
551 }
552 
553 // The test checks that ViewID_OVR and InstanceID have the correct initializers based on the
554 // number of views.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,ViewIDAndInstanceIDHaveCorrectValues)555 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectValues)
556 {
557     const std::string &shaderString =
558         "#version 300 es\n"
559         "#extension GL_OVR_multiview : require\n"
560         "layout(num_views = 3) in;\n"
561         "flat out int myInstance;\n"
562         "void main()\n"
563         "{\n"
564         "   gl_Position.x = gl_ViewID_OVR == 0u ? 0. : 1.;\n"
565         "   gl_Position.yzw = vec3(0., 0., 1.);\n"
566         "   myInstance = gl_InstanceID;\n"
567         "}\n";
568     requestHLSLOutput();
569 
570     ShCompileOptions compileOptions                        = {};
571     compileOptions.initializeBuiltinsForInstancedMultiview = true;
572 
573     compile(shaderString, compileOptions);
574 
575     EXPECT_TRUE(foundInAllGLSLCode("ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
576     EXPECT_TRUE(foundInAllGLSLCode("InstanceID = int((uint(gl_InstanceID) / 3u))"));
577 
578     EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uint_ctor_int(gl_InstanceID) % 3)"));
579 #if defined(ANGLE_ENABLE_HLSL)
580     EXPECT_FALSE(foundInHLSLCode("_ViewID_OVR = (uint_ctor_int(gl_InstanceID) % 3)"));
581 #endif
582     EXPECT_TRUE(foundInHLSLCode("InstanceID = int_ctor_uint((uint_ctor_int(gl_InstanceID) / 3))"));
583 }
584 
585 // The test checks that the directive enabling GL_OVR_multiview is not outputted if the extension
586 // is emulated.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,StrippedOVRMultiviewDirective)587 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, StrippedOVRMultiviewDirective)
588 {
589     const std::string &shaderString =
590         "#version 300 es\n"
591         "#extension GL_OVR_multiview : require\n"
592         "layout(num_views = 3) in;\n"
593         "void main()\n"
594         "{\n"
595         "}\n";
596     // The directive must not be present if any of the multiview emulation options are set.
597     ShCompileOptions compileOptions                        = {};
598     compileOptions.initializeBuiltinsForInstancedMultiview = true;
599     compile(shaderString, compileOptions);
600     EXPECT_FALSE(foundInESSLCode("GL_OVR_multiview"));
601     EXPECT_FALSE(foundInGLSLCode("GL_OVR_multiview"));
602 
603     // The directive should be outputted from the ESSL translator with none of the options being
604     // set.
605     compile(shaderString);
606     EXPECT_TRUE(foundInESSLCode("GL_OVR_multiview"));
607 }
608 
609 // Test that ViewID_OVR has a proper qualifier in an ESSL 3.00 fragment shader.
TEST_F(OVRMultiviewFragmentShaderTest,ViewIDDeclaredAsViewID)610 TEST_F(OVRMultiviewFragmentShaderTest, ViewIDDeclaredAsViewID)
611 {
612     const std::string &shaderString =
613         "#version 300 es\n"
614         "#extension GL_OVR_multiview : require\n"
615         "void main()\n"
616         "{\n"
617         "}\n";
618     mCompileOptions.initializeBuiltinsForInstancedMultiview = true;
619     compileAssumeSuccess(shaderString);
620     VariableOccursNTimes(mASTRoot, ImmutableString("ViewID_OVR"), EvqViewIDOVR, 1u);
621 }
622 
623 // The test checks that the GL_NV_viewport_array2 extension is emitted in a vertex shader if the
624 // selectViewInNvGLSLVertexShader option is set.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,ViewportArray2IsEmitted)625 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsEmitted)
626 {
627     const std::string &shaderString =
628         "#version 300 es\n"
629         "#extension GL_OVR_multiview : require\n"
630         "layout(num_views = 3) in;\n"
631         "void main()\n"
632         "{\n"
633         "}\n";
634     compile(shaderString, mMultiviewCompileOptions);
635     EXPECT_TRUE(foundInAllGLSLCode("#extension GL_NV_viewport_array2 : require"));
636 }
637 
638 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a vertex shader if the
639 // OVR_multiview2 extension is not requested in the shader source even if the
640 // selectViewInNvGLSLVertexShader option is set.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,ViewportArray2IsNotEmitted)641 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, ViewportArray2IsNotEmitted)
642 {
643     const std::string &shaderString =
644         "#version 300 es\n"
645         "void main()\n"
646         "{\n"
647         "}\n";
648     compile(shaderString, mMultiviewCompileOptions);
649     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
650     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
651 }
652 
653 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a fragment shader if
654 // the selectViewInNvGLSLVertexShader option is set.
TEST_F(OVRMultiviewFragmentShaderOutputCodeTest,ViewportArray2IsNotEmitted)655 TEST_F(OVRMultiviewFragmentShaderOutputCodeTest, ViewportArray2IsNotEmitted)
656 {
657     const std::string &shaderString =
658         "#version 300 es\n"
659         "#extension GL_OVR_multiview : require\n"
660         "void main()\n"
661         "{\n"
662         "}\n";
663     compile(shaderString, mMultiviewCompileOptions);
664     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
665     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
666 }
667 
668 // The test checks if OVR_multiview is emitted only once and no other
669 // multiview extensions are emitted.
TEST_F(OVRMultiviewFragmentShaderOutputCodeTest,NativeOvrMultiviewOutput)670 TEST_F(OVRMultiviewFragmentShaderOutputCodeTest, NativeOvrMultiviewOutput)
671 {
672     const std::string &shaderString =
673         "#version 300 es\n"
674         "#extension GL_OVR_multiview : require\n"
675         "void main()\n"
676         "{\n"
677         "}\n";
678     compile(shaderString);
679     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
680     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
681 
682     EXPECT_TRUE(foundInESSLCode("#extension GL_OVR_multiview"));
683     EXPECT_TRUE(foundInGLSLCode("#extension GL_OVR_multiview"));
684 
685     EXPECT_FALSE(foundInESSLCode("#extension GL_OVR_multiview2"));
686     EXPECT_FALSE(foundInGLSLCode("#extension GL_OVR_multiview2"));
687 
688     // no double extension
689     std::vector<const char *> notExpectedStrings1 = {"#extension GL_OVR_multiview",
690                                                      "#extension GL_OVR_multiview"};
691     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings1));
692     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings1));
693 }
694 
695 // The test checks that the GL_NV_viewport_array2 extension is not emitted in a compute shader if
696 // the selectViewInNvGLSLVertexShader option is set.
TEST_F(OVRMultiviewComputeShaderOutputCodeTest,ViewportArray2IsNotEmitted)697 TEST_F(OVRMultiviewComputeShaderOutputCodeTest, ViewportArray2IsNotEmitted)
698 {
699     const std::string &shaderString =
700         R"(#version 310 es
701         #extension GL_OVR_multiview : require
702         void main()
703         {
704         })";
705     compile(shaderString, mMultiviewCompileOptions);
706     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
707     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
708 }
709 
710 // The test checks that the layer is selected after the initialization of ViewID_OVR for
711 // GLSL and ESSL ouputs.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,GlLayerIsSet)712 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, GlLayerIsSet)
713 {
714     const std::string &shaderString =
715         "#version 300 es\n"
716         "#extension GL_OVR_multiview : require\n"
717         "layout(num_views = 3) in;\n"
718         "void main()\n"
719         "{\n"
720         "}\n";
721     compile(shaderString, mMultiviewCompileOptions);
722 
723     std::vector<const char *> expectedStrings = {
724         "ViewID_OVR = (uint(gl_InstanceID) % 3u)",
725         "gl_Layer = (int(ViewID_OVR) + multiviewBaseViewLayerIndex)"};
726     EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
727     EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
728 }
729 
730 // Test that the OVR_multiview without emulation emits OVR_multiview output.
731 // It also tests that the GL_OVR_multiview is emitted only once and no other
732 // multiview extensions are emitted.
TEST_F(OVRMultiviewVertexShaderOutputCodeTest,NativeOvrMultiviewOutput)733 TEST_F(OVRMultiviewVertexShaderOutputCodeTest, NativeOvrMultiviewOutput)
734 {
735     const std::string &shaderString =
736         "#version 300 es\n"
737         "#extension GL_OVR_multiview : require\n"
738         "layout(num_views = 3) in;\n"
739         "void main()\n"
740         "{\n"
741         "}\n";
742     compile(shaderString);
743 
744     std::vector<const char *> expectedStrings = {"#extension GL_OVR_multiview", "layout(num_views"};
745     EXPECT_TRUE(foundInCodeInOrder(SH_ESSL_OUTPUT, expectedStrings));
746     EXPECT_TRUE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, expectedStrings));
747 
748     EXPECT_FALSE(foundInGLSLCode("#extension GL_NV_viewport_array2"));
749     EXPECT_FALSE(foundInESSLCode("#extension GL_NV_viewport_array2"));
750 
751     EXPECT_FALSE(foundInGLSLCode("#extension GL_OVR_multiview2"));
752     EXPECT_FALSE(foundInESSLCode("#extension GL_OVR_multiview2"));
753 
754     EXPECT_FALSE(foundInGLSLCode("gl_ViewportIndex"));
755     EXPECT_FALSE(foundInESSLCode("gl_ViewportIndex"));
756 
757     // no double extension
758     std::vector<const char *> notExpectedStrings1 = {"#extension GL_OVR_multiview",
759                                                      "#extension GL_OVR_multiview"};
760     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings1));
761     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings1));
762 
763     // no double num_views
764     std::vector<const char *> notExpectedStrings2 = {"layout(num_views", "layout(num_views"};
765     EXPECT_FALSE(foundInCodeInOrder(SH_ESSL_OUTPUT, notExpectedStrings2));
766     EXPECT_FALSE(foundInCodeInOrder(SH_GLSL_COMPATIBILITY_OUTPUT, notExpectedStrings2));
767 }
768 
769 }  // namespace
770