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