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