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