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