1#include "ANGLETest.h"
2
3class GLSLTest : public ANGLETest
4{
5protected:
6    GLSLTest()
7    {
8        setWindowWidth(128);
9        setWindowHeight(128);
10        setConfigRedBits(8);
11        setConfigGreenBits(8);
12        setConfigBlueBits(8);
13        setConfigAlphaBits(8);
14    }
15
16    virtual void SetUp()
17    {
18        ANGLETest::SetUp();
19
20        mSimpleVSSource = SHADER_SOURCE
21        (
22            attribute vec4 inputAttribute;
23            void main()
24            {
25                gl_Position = inputAttribute;
26            }
27        );
28    }
29
30    std::string GenerateVaryingType(GLint vectorSize)
31    {
32        char varyingType[10];
33
34        if (vectorSize == 1)
35        {
36            sprintf(varyingType, "float");
37        }
38        else
39        {
40            sprintf(varyingType, "vec%d", vectorSize);
41        }
42
43        return std::string(varyingType);
44    }
45
46    std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
47    {
48        char buff[100];
49
50        if (arraySize == 1)
51        {
52            sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
53        }
54        else
55        {
56            sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id, arraySize);
57        }
58
59        return std::string(buff);
60    }
61
62    std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
63    {
64        std::string returnString;
65        char buff[100];
66
67        if (arraySize == 1)
68        {
69            sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
70            returnString += buff;
71        }
72        else
73        {
74            for (int i = 0; i < arraySize; i++)
75            {
76                sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i, GenerateVaryingType(vectorSize).c_str());
77                returnString += buff;
78            }
79        }
80
81        return returnString;
82    }
83
84    std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
85    {
86        if (arraySize == 1)
87        {
88            char buff[100];
89            sprintf(buff, "v%d + ", id);
90            return std::string(buff);
91        }
92        else
93        {
94            std::string returnString;
95            for (int i = 0; i < arraySize; i++)
96            {
97                char buff[100];
98                sprintf(buff, "v%d[%d] + ", id, i);
99                returnString += buff;
100            }
101            return returnString;
102        }
103    }
104
105    void GenerateGLSLWithVaryings(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount, std::string* fragmentShader, std::string* vertexShader)
106    {
107        // Generate a string declaring the varyings, to share between the fragment shader and the vertex shader.
108        std::string varyingDeclaration;
109
110        unsigned int varyingCount = 0;
111
112        for (GLint i = 0; i < floatCount; i++)
113        {
114            varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
115            varyingCount += 1;
116        }
117
118        for (GLint i = 0; i < floatArrayCount; i++)
119        {
120            varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
121            varyingCount += 1;
122        }
123
124        for (GLint i = 0; i < vec2Count; i++)
125        {
126            varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
127            varyingCount += 1;
128        }
129
130        for (GLint i = 0; i < vec2ArrayCount; i++)
131        {
132            varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
133            varyingCount += 1;
134        }
135
136        for (GLint i = 0; i < vec3Count; i++)
137        {
138            varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
139            varyingCount += 1;
140        }
141
142        for (GLint i = 0; i < vec3ArrayCount; i++)
143        {
144            varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
145            varyingCount += 1;
146        }
147
148        // Generate the vertex shader
149        vertexShader->clear();
150        vertexShader->append(varyingDeclaration);
151        vertexShader->append("\nvoid main()\n{\n");
152
153        unsigned int currentVSVarying = 0;
154
155        for (GLint i = 0; i < floatCount; i++)
156        {
157            vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
158            currentVSVarying += 1;
159        }
160
161        for (GLint i = 0; i < floatArrayCount; i++)
162        {
163            vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
164            currentVSVarying += 1;
165        }
166
167        for (GLint i = 0; i < vec2Count; i++)
168        {
169            vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
170            currentVSVarying += 1;
171        }
172
173        for (GLint i = 0; i < vec2ArrayCount; i++)
174        {
175            vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
176            currentVSVarying += 1;
177        }
178
179        for (GLint i = 0; i < vec3Count; i++)
180        {
181            vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
182            currentVSVarying += 1;
183        }
184
185        for (GLint i = 0; i < vec3ArrayCount; i++)
186        {
187            vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
188            currentVSVarying += 1;
189        }
190
191        vertexShader->append("}\n");
192
193        // Generate the fragment shader
194        fragmentShader->clear();
195        fragmentShader->append("precision highp float;\n");
196        fragmentShader->append(varyingDeclaration);
197        fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
198
199        unsigned int currentFSVarying = 0;
200
201        // Make use of the float varyings
202        fragmentShader->append("\tretColor += vec4(");
203
204        for (GLint i = 0; i < floatCount; i++)
205        {
206            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
207            currentFSVarying += 1;
208        }
209
210        for (GLint i = 0; i < floatArrayCount; i++)
211        {
212            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
213            currentFSVarying += 1;
214        }
215
216        fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
217
218        // Make use of the vec2 varyings
219        fragmentShader->append("\tretColor += vec4(");
220
221        for (GLint i = 0; i < vec2Count; i++)
222        {
223            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
224            currentFSVarying += 1;
225        }
226
227        for (GLint i = 0; i < vec2ArrayCount; i++)
228        {
229            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
230            currentFSVarying += 1;
231        }
232
233        fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
234
235        // Make use of the vec3 varyings
236        fragmentShader->append("\tretColor += vec4(");
237
238        for (GLint i = 0; i < vec3Count; i++)
239        {
240            fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
241            currentFSVarying += 1;
242        }
243
244        for (GLint i = 0; i < vec3ArrayCount; i++)
245        {
246            fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
247            currentFSVarying += 1;
248        }
249
250        fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
251        fragmentShader->append("\tgl_FragColor = retColor;\n}");
252    }
253
254    std::string mSimpleVSSource;
255};
256
257TEST_F(GLSLTest, NamelessScopedStructs)
258{
259    const std::string fragmentShaderSource = SHADER_SOURCE
260    (
261        precision mediump float;
262
263        void main()
264        {
265            struct
266            {
267                float q;
268            } b;
269
270            gl_FragColor = vec4(1, 0, 0, 1);
271            gl_FragColor.a += b.q;
272        }
273    );
274
275    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
276    EXPECT_NE(0u, program);
277}
278TEST_F(GLSLTest, ScopedStructsOrderBug)
279{
280    const std::string fragmentShaderSource = SHADER_SOURCE
281    (
282        precision mediump float;
283
284        struct T
285        {
286            float f;
287        };
288
289        void main()
290        {
291            T a;
292
293            struct T
294            {
295                float q;
296            };
297
298            T b;
299
300            gl_FragColor = vec4(1, 0, 0, 1);
301            gl_FragColor.a += a.f;
302            gl_FragColor.a += b.q;
303        }
304    );
305
306    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
307    EXPECT_NE(0u, program);
308}
309
310TEST_F(GLSLTest, ScopedStructsBug)
311{
312    const std::string fragmentShaderSource = SHADER_SOURCE
313    (
314        precision mediump float;
315
316        struct T_0
317        {
318            float f;
319        };
320
321        void main()
322        {
323            gl_FragColor = vec4(1, 0, 0, 1);
324
325            struct T
326            {
327                vec2 v;
328            };
329
330            T_0 a;
331            T b;
332
333            gl_FragColor.a += a.f;
334            gl_FragColor.a += b.v.x;
335        }
336    );
337
338    GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
339    EXPECT_NE(0u, program);
340}
341
342TEST_F(GLSLTest, DxPositionBug)
343{
344    const std::string &vertexShaderSource = SHADER_SOURCE
345    (
346        attribute vec4 inputAttribute;
347        varying float dx_Position;
348        void main()
349        {
350            gl_Position = vec4(inputAttribute);
351            dx_Position = 0.0;
352        }
353    );
354
355    const std::string &fragmentShaderSource = SHADER_SOURCE
356    (
357        precision mediump float;
358
359        varying float dx_Position;
360
361        void main()
362        {
363            gl_FragColor = vec4(dx_Position, 0, 0, 1);
364        }
365    );
366
367    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
368    EXPECT_NE(0u, program);
369}
370
371TEST_F(GLSLTest, ElseIfRewriting)
372{
373    const std::string &vertexShaderSource =
374        "attribute vec4 a_position;\n"
375        "varying float v;\n"
376        "void main() {\n"
377        "  gl_Position = a_position;\n"
378        "  v = 1.0;\n"
379        "  if (a_position.x <= 0.5) {\n"
380        "    v = 0.0;\n"
381        "  } else if (a_position.x >= 0.5) {\n"
382        "    v = 2.0;\n"
383        "  }\n"
384        "}\n";
385
386    const std::string &fragmentShaderSource =
387        "precision highp float;\n"
388        "varying float v;\n"
389        "void main() {\n"
390        "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
391        "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
392        "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
393        "  gl_FragColor = color;\n"
394        "}\n";
395
396    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
397    ASSERT_NE(0u, program);
398
399    drawQuad(program, "a_position", 0.5f);
400    swapBuffers();
401
402    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
403    EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
404}
405
406TEST_F(GLSLTest, TwoElseIfRewriting)
407{
408    const std::string &vertexShaderSource =
409        "attribute vec4 a_position;\n"
410        "varying float v;\n"
411        "void main() {\n"
412        "  gl_Position = a_position;\n"
413        "  if (a_position.x == 0.0) {\n"
414        "    v = 1.0;\n"
415        "  } else if (a_position.x > 0.5) {\n"
416        "    v = 0.0;\n"
417        "  } else if (a_position.x > 0.75) {\n"
418        "    v = 0.5;\n"
419        "  }\n"
420        "}\n";
421
422    const std::string &fragmentShaderSource =
423        "precision highp float;\n"
424        "varying float v;\n"
425        "void main() {\n"
426        "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
427        "}\n";
428
429    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
430    EXPECT_NE(0u, program);
431}
432
433TEST_F(GLSLTest, InvariantVaryingOut)
434{
435    const std::string fragmentShaderSource = SHADER_SOURCE
436    (
437        precision mediump float;
438        varying float v_varying;
439        void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }
440    );
441
442    const std::string vertexShaderSource = SHADER_SOURCE
443    (
444        attribute vec4 a_position;
445        invariant varying float v_varying;
446        void main() { v_varying = a_position.x; gl_Position = a_position; }
447    );
448
449    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
450    EXPECT_NE(0u, program);
451}
452
453TEST_F(GLSLTest, FrontFacingAndVarying)
454{
455    const std::string vertexShaderSource = SHADER_SOURCE
456    (
457        attribute vec4 a_position;
458        varying float v_varying;
459        void main()
460        {
461            v_varying = a_position.x;
462            gl_Position = a_position;
463        }
464    );
465
466    const std::string fragmentShaderSource = SHADER_SOURCE
467    (
468        precision mediump float;
469        varying float v_varying;
470        void main()
471        {
472            vec4 c;
473
474            if (gl_FrontFacing)
475            {
476                c = vec4(v_varying, 0, 0, 1.0);
477            }
478            else
479            {
480                c = vec4(0, v_varying, 0, 1.0);
481            }
482            gl_FragColor = c;
483        }
484    );
485
486    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
487    EXPECT_NE(0u, program);
488}
489
490TEST_F(GLSLTest, InvariantVaryingIn)
491{
492    const std::string fragmentShaderSource = SHADER_SOURCE
493    (
494        precision mediump float;
495        invariant varying float v_varying;
496        void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }
497    );
498
499    const std::string vertexShaderSource = SHADER_SOURCE
500    (
501        attribute vec4 a_position;
502        varying float v_varying;
503        void main() { v_varying = a_position.x; gl_Position = a_position; }
504    );
505
506    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
507    EXPECT_NE(0u, program);
508}
509
510TEST_F(GLSLTest, InvariantVaryingBoth)
511{
512    const std::string fragmentShaderSource = SHADER_SOURCE
513    (
514        precision mediump float;
515        invariant varying float v_varying;
516        void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }
517    );
518
519    const std::string vertexShaderSource = SHADER_SOURCE
520    (
521        attribute vec4 a_position;
522        invariant varying float v_varying;
523        void main() { v_varying = a_position.x; gl_Position = a_position; }
524    );
525
526    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
527    EXPECT_NE(0u, program);
528}
529
530TEST_F(GLSLTest, InvariantGLPosition)
531{
532    const std::string fragmentShaderSource = SHADER_SOURCE
533    (
534        precision mediump float;
535        varying float v_varying;
536        void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }
537    );
538
539    const std::string vertexShaderSource = SHADER_SOURCE
540    (
541        attribute vec4 a_position;
542        invariant gl_Position;
543        varying float v_varying;
544        void main() { v_varying = a_position.x; gl_Position = a_position; }
545    );
546
547    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
548    EXPECT_NE(0u, program);
549}
550
551TEST_F(GLSLTest, InvariantAll)
552{
553    const std::string fragmentShaderSource = SHADER_SOURCE
554    (
555        precision mediump float;
556        varying float v_varying;
557        void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }
558    );
559
560    const std::string vertexShaderSource =
561        "#pragma STDGL invariant(all)\n"
562        "attribute vec4 a_position;\n"
563        "varying float v_varying;\n"
564        "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
565
566    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
567    EXPECT_NE(0u, program);
568}
569
570TEST_F(GLSLTest, MaxVaryingVec3)
571{
572    GLint maxVaryings = 0;
573    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
574
575    std::string fragmentShaderSource;
576    std::string vertexShaderSource;
577
578    GenerateGLSLWithVaryings(0, 0, 0, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource);
579
580    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
581    EXPECT_NE(0u, program);
582}
583
584TEST_F(GLSLTest, MaxVaryingVec3Array)
585{
586    GLint maxVaryings = 0;
587    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
588
589    std::string fragmentShaderSource;
590    std::string vertexShaderSource;
591
592    GenerateGLSLWithVaryings(0, 0, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource);
593
594    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
595    EXPECT_NE(0u, program);
596}
597
598TEST_F(GLSLTest, MaxVaryingVec3AndOneFloat)
599{
600    GLint maxVaryings = 0;
601    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
602
603    std::string fragmentShaderSource;
604    std::string vertexShaderSource;
605
606    GenerateGLSLWithVaryings(1, 0, 0, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource);
607
608    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
609    EXPECT_NE(0u, program);
610}
611
612TEST_F(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
613{
614    GLint maxVaryings = 0;
615    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
616
617    std::string fragmentShaderSource;
618    std::string vertexShaderSource;
619
620    GenerateGLSLWithVaryings(0, 1, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource);
621
622    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
623    EXPECT_NE(0u, program);
624}
625
626TEST_F(GLSLTest, TwiceMaxVaryingVec2)
627{
628    GLint maxVaryings = 0;
629    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
630
631    std::string fragmentShaderSource;
632    std::string vertexShaderSource;
633
634    GenerateGLSLWithVaryings(0, 0, 2 * maxVaryings, 0, 0, 0, &fragmentShaderSource, &vertexShaderSource);
635
636    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
637    EXPECT_NE(0u, program);
638}
639
640TEST_F(GLSLTest, MaxVaryingVec2Arrays)
641{
642    GLint maxVaryings = 0;
643    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
644
645    std::string fragmentShaderSource;
646    std::string vertexShaderSource;
647
648    GenerateGLSLWithVaryings(0, 0, 0, maxVaryings, 0, 0, &fragmentShaderSource, &vertexShaderSource);
649
650    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
651    EXPECT_NE(0u, program);
652}
653
654TEST_F(GLSLTest, MaxPlusOneVaryingVec3)
655{
656    GLint maxVaryings = 0;
657    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
658
659    std::string fragmentShaderSource;
660    std::string vertexShaderSource;
661
662    GenerateGLSLWithVaryings(0, 0, 0, 0, maxVaryings + 1, 0, &fragmentShaderSource, &vertexShaderSource);
663
664    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
665    EXPECT_EQ(0u, program);
666}
667
668TEST_F(GLSLTest, MaxPlusOneVaryingVec3Array)
669{
670    GLint maxVaryings = 0;
671    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
672
673    std::string fragmentShaderSource;
674    std::string vertexShaderSource;
675
676    GenerateGLSLWithVaryings(0, 0, 0, 0, 0, maxVaryings / 2 + 1, &fragmentShaderSource, &vertexShaderSource);
677
678    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
679    EXPECT_EQ(0u, program);
680}
681
682TEST_F(GLSLTest, MaxVaryingVec3AndOneVec2)
683{
684    GLint maxVaryings = 0;
685    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
686
687    std::string fragmentShaderSource;
688    std::string vertexShaderSource;
689
690    GenerateGLSLWithVaryings(0, 0, 1, 0, maxVaryings, 0, &fragmentShaderSource, &vertexShaderSource);
691
692    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
693    EXPECT_EQ(0u, program);
694}
695
696TEST_F(GLSLTest, MaxPlusOneVaryingVec2)
697{
698    GLint maxVaryings = 0;
699    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
700
701    std::string fragmentShaderSource;
702    std::string vertexShaderSource;
703
704    GenerateGLSLWithVaryings(0, 0, 2 * maxVaryings + 1, 0, 0, 0, &fragmentShaderSource, &vertexShaderSource);
705
706    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
707    EXPECT_EQ(0u, program);
708}
709
710TEST_F(GLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
711{
712    GLint maxVaryings = 0;
713    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
714
715    std::string fragmentShaderSource;
716    std::string vertexShaderSource;
717
718    GenerateGLSLWithVaryings(0, maxVaryings / 2 + 1, 0, 0, 0, maxVaryings / 2, &fragmentShaderSource, &vertexShaderSource);
719
720    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
721    EXPECT_EQ(0u, program);
722}
723