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