xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ShaderOpTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 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 // Tests for shader interpolation qualifiers
7 //
8 
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 
12 using namespace angle;
13 
14 constexpr int kPixelColorThreshhold = 8;
15 
16 class ShaderOpTest : public ANGLETest<>
17 {
18   protected:
ShaderOpTest()19     ShaderOpTest() : ANGLETest()
20     {
21         setWindowWidth(256);
22         setWindowHeight(256);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27         setConfigDepthBits(24);
28         setConfigStencilBits(8);
29         setMultisampleEnabled(0);
30     }
31 };
32 
33 // Simplified test from dEQP-GLES2.functional.fragment_ops.interaction.basic_shader.22
34 // Test that vulkan drivers correctly handle the constant expression spirv generated by ANGLE
TEST_P(ShaderOpTest,ConstantExpression)35 TEST_P(ShaderOpTest, ConstantExpression)
36 {
37     const char *vertSrc = R"(
38 attribute vec4 pos;
39 
40 void main()
41 {
42     gl_Position = pos;
43 }
44 )";
45     // ANGLE and glslang translate below expression in fragment shader differently
46     // vec4 c = vec4(1.0, 0.5, 0.5, 0.75)
47 
48     // ANGLE:
49     // %constVec4 = OpConstantComposite %vec4 %const1 %const2 %const2 %const3
50     // %var = OpVariable %PrivateVec4Pointer Private %constVec4
51     // %loadedVal = OpLoad %vec4 %var
52     // OpStore %gl_fragColor %loadedVal
53 
54     // glslang:
55     // %constVec4 = OpConstantComposite %vec4 %const1 %const2 %const2 %const3
56     // %var = OpVariable %PrivateVec4Pointer Private
57     // OpStore %var %constVec4
58     // %loadedVal = OpLoad %vec4 %var
59     // OpStore %gl_fragColor %loadedVal
60 
61     // Both are valid spirv instructions.
62     // Tests should pass with spirv generated by ANGLE.
63 
64     // Note: setting forceDeferNonConstGlobalInitializers to true will make ANGLE generate the same
65     // spirv instruction for the constant expression as glslang.
66     const char *fragSrc = R"(
67 precision mediump float;
68 vec4 c = vec4(1.0, 0.5, 0.5, 0.75);
69 
70 void main()
71 {
72     gl_FragColor = c;
73 }
74 )";
75     ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
76     glUseProgram(program);
77 
78     std::array<GLfloat, 16> attribPosData = {1, 1,  0.5, 1, -1, 1,  0.5, 1,
79                                              1, -1, 0.5, 1, -1, -1, 0.5, 1};
80     GLint attribPosLoc                    = glGetAttribLocation(1, "pos");
81     ASSERT(attribPosLoc >= 0);
82     glEnableVertexAttribArray(attribPosLoc);
83     glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data());
84 
85     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
86     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
87     EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 125, 125, 190), kPixelColorThreshhold);
88 }
89 
90 // Simplified test from dEQP-GLES2.functional.shaders.random.all_features.fragment.12
91 // Test that vulkan drivers correctly handle the constant expression spirv generated by ANGLE
92 // Difference beween this test and ConstantExpression test is there is a uniform in fragment shader
93 // in this test, and with this extra element the ANGLE spirv can trigger an error in
94 // vkCreateGraphicsPipelines on some drivers.
TEST_P(ShaderOpTest,ConstantExpressionComparedWithUniform)95 TEST_P(ShaderOpTest, ConstantExpressionComparedWithUniform)
96 {
97     const char *vertSrc = R"(
98 attribute vec4 pos;
99 void main()
100 {
101     gl_Position = pos;
102 }
103 )";
104 
105     // ANGLE and glslang translate below expression in fragment shader differently
106     // int k = (5) * (1)
107 
108     // ANGLE:
109     // %k = OpVariable %_ptr_Private_int_0 Private %int_5 // declare Private OpVariable with
110     // initializer
111     // ... some other instructions
112     // %main = OpFunction %void None %62
113     // %67 = OpLoad %int %k
114     // ... some other instructions
115 
116     // glslang:
117     // %k = OpVariable %_ptr_Private_int_0 Private // declare Private OpVariable without initializer
118     // ... some other instructions
119     // %main = OpFunction %void None %62
120     // OpStore %k %int_5 // Assign the value to the Private OpVariable in the main function
121     // %67 = OpLoad %int %k
122     // ... some other instructions
123 
124     // Both are valid spirv instructions.
125     // Tests should pass with spirv generated by ANGLE
126 
127     // Note: setting forceDeferNonConstGlobalInitializers to true will make ANGLE generate the same
128     // spirv instruction for the constant expression as glslang.
129 
130     const char *fragSrc = R"(
131 precision mediump float;
132 int k = (5) * (1);
133 uniform mediump int o;
134 void main()
135 {
136     gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
137     if (o >= k)
138         gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
139 }
140 )";
141     ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
142     glUseProgram(program);
143     EXPECT_GL_NO_ERROR();
144 
145     std::array<GLfloat, 16> attribPosData = {1, 1,  0.5, 1, -1, 1,  0.5, 1,
146                                              1, -1, 0.5, 1, -1, -1, 0.5, 1};
147     GLint attribPosLoc                    = glGetAttribLocation(1, "pos");
148     ASSERT(attribPosLoc >= 0);
149     glEnableVertexAttribArray(attribPosLoc);
150     glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data());
151     EXPECT_GL_NO_ERROR();
152 
153     GLint uniformOLocation = glGetUniformLocation(program, "o");
154     ASSERT(uniformOLocation >= 0);
155     GLint uniformOValue = 4;
156     glUniform1i(uniformOLocation, uniformOValue);
157 
158     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
159     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
160     EXPECT_GL_NO_ERROR();
161     EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 255, 255, 255), kPixelColorThreshhold);
162 }
163 
164 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderOpTest);
165 ANGLE_INSTANTIATE_TEST_ES2(ShaderOpTest);
166