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