xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/APPLE_clip_distance_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 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 // APPLE_clip_distance_test.cpp:
7 //   Test for APPLE_clip_distance
8 //
9 
10 #include "tests/test_utils/ShaderExtensionTest.h"
11 
12 namespace
13 {
14 const char EXTPragma[] = "#extension GL_APPLE_clip_distance : require\n";
15 
16 // Shader using gl_ClipDistance
17 const char ESSL100_APPLEClipDistanceShader1[] =
18     R"(
19     uniform vec4 uPlane;
20 
21     attribute vec4 aPosition;
22 
23     void main()
24     {
25         gl_Position = aPosition;
26         gl_ClipDistance[1] = dot(aPosition, uPlane);
27     })";
28 
29 // Shader redeclares gl_ClipDistance
30 const char ESSL100_APPLEClipDistanceShader2[] =
31     R"(
32     uniform vec4 uPlane;
33 
34     attribute vec4 aPosition;
35 
36     varying highp float gl_ClipDistance[4];
37 
38     void main()
39     {
40         gl_Position = aPosition;
41         gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
42         gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
43     })";
44 
45 // ESSL 3.00 Shader using gl_ClipDistance
46 const char ESSL300_APPLEClipDistanceShader1[] =
47     R"(
48     uniform vec4 uPlane;
49 
50     in vec4 aPosition;
51 
52     void main()
53     {
54         gl_Position = aPosition;
55         gl_ClipDistance[1] = dot(aPosition, uPlane);
56     })";
57 
58 // ESSL 3.00 Shader redeclares gl_ClipDistance
59 const char ESSL300_APPLEClipDistanceShader2[] =
60     R"(
61     uniform vec4 uPlane;
62 
63     in vec4 aPosition;
64 
65     out highp float gl_ClipDistance[4];
66 
67     void main()
68     {
69         gl_Position = aPosition;
70         gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
71         gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
72     })";
73 
74 class APPLEClipDistanceTest : public sh::ShaderExtensionTest
75 {
76   public:
InitializeCompiler()77     void InitializeCompiler() { InitializeCompiler(SH_GLSL_130_OUTPUT); }
InitializeCompiler(ShShaderOutput shaderOutputType)78     void InitializeCompiler(ShShaderOutput shaderOutputType)
79     {
80         DestroyCompiler();
81 
82         mCompiler = sh::ConstructCompiler(GL_VERTEX_SHADER, testing::get<0>(GetParam()),
83                                           shaderOutputType, &mResources);
84         ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
85     }
86 
TestShaderCompile(const char * pragma)87     testing::AssertionResult TestShaderCompile(const char *pragma)
88     {
89         const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
90                                        testing::get<2>(GetParam())};
91 
92         ShCompileOptions compileOptions = {};
93         compileOptions.objectCode       = true;
94 
95         bool success = sh::Compile(mCompiler, shaderStrings, 3, compileOptions);
96         if (success)
97         {
98             return ::testing::AssertionSuccess() << "Compilation success";
99         }
100         return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
101     }
102 };
103 
104 // Extension flag is required to compile properly. Expect failure when it is
105 // not present.
TEST_P(APPLEClipDistanceTest,CompileFailsWithoutExtension)106 TEST_P(APPLEClipDistanceTest, CompileFailsWithoutExtension)
107 {
108     mResources.APPLE_clip_distance = 0;
109     InitializeCompiler();
110     EXPECT_FALSE(TestShaderCompile(EXTPragma));
111 }
112 
113 // Extension directive is required to compile properly. Expect failure when
114 // it is not present.
TEST_P(APPLEClipDistanceTest,CompileFailsWithExtensionWithoutPragma)115 TEST_P(APPLEClipDistanceTest, CompileFailsWithExtensionWithoutPragma)
116 {
117     mResources.APPLE_clip_distance = 1;
118     InitializeCompiler();
119     EXPECT_FALSE(TestShaderCompile(""));
120 }
121 
122 // With extension flag and extension directive, compiling succeeds.
123 // Also test that the extension directive state is reset correctly.
TEST_P(APPLEClipDistanceTest,CompileSucceedsWithExtensionAndPragma)124 TEST_P(APPLEClipDistanceTest, CompileSucceedsWithExtensionAndPragma)
125 {
126     mResources.APPLE_clip_distance = 1;
127     mResources.MaxClipDistances    = 8;
128     InitializeCompiler();
129     EXPECT_TRUE(TestShaderCompile(EXTPragma));
130     // Test reset functionality.
131     EXPECT_FALSE(TestShaderCompile(""));
132     EXPECT_TRUE(TestShaderCompile(EXTPragma));
133 }
134 
135 #if defined(ANGLE_ENABLE_VULKAN)
136 // With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(APPLEClipDistanceTest,CompileSucceedsVulkan)137 TEST_P(APPLEClipDistanceTest, CompileSucceedsVulkan)
138 {
139     mResources.APPLE_clip_distance = 1;
140     mResources.MaxClipDistances    = 8;
141 
142     InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
143     EXPECT_TRUE(TestShaderCompile(EXTPragma));
144 }
145 
146 // Test that the SPIR-V gen path can compile a shader when this extension is not supported.
TEST_P(APPLEClipDistanceTest,CompileSucceedsWithoutExtSupportVulkan)147 TEST_P(APPLEClipDistanceTest, CompileSucceedsWithoutExtSupportVulkan)
148 {
149     mResources.APPLE_clip_distance = 0;
150     mResources.MaxClipDistances    = 0;
151     mResources.MaxCullDistances    = 0;
152 
153     InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
154 
155     constexpr char kNoClipCull[] = R"(
156     void main()
157     {
158         gl_Position = vec4(0);
159     })";
160     const char *shaderStrings[]  = {kNoClipCull};
161 
162     ShCompileOptions compileOptions = {};
163     compileOptions.objectCode       = true;
164 
165     bool success = sh::Compile(mCompiler, shaderStrings, 1, compileOptions);
166     if (success)
167     {
168         ::testing::AssertionSuccess() << "Compilation success";
169     }
170     else
171     {
172         ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
173     }
174 
175     EXPECT_TRUE(success);
176 }
177 #endif
178 
179 #if defined(ANGLE_ENABLE_METAL)
180 // With extension flag and extension directive, compiling using TranslatorMSL succeeds.
TEST_P(APPLEClipDistanceTest,CompileSucceedsMetal)181 TEST_P(APPLEClipDistanceTest, CompileSucceedsMetal)
182 {
183     mResources.APPLE_clip_distance = 1;
184     mResources.MaxClipDistances    = 8;
185 
186     InitializeCompiler(SH_MSL_METAL_OUTPUT);
187     EXPECT_TRUE(TestShaderCompile(EXTPragma));
188 }
189 #endif
190 
191 // The SL #version 100 shaders that are correct work similarly
192 // in both GL2 and GL3, with and without the version string.
193 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
194                          APPLEClipDistanceTest,
195                          Combine(Values(SH_GLES2_SPEC),
196                                  Values(sh::ESSLVersion100),
197                                  Values(ESSL100_APPLEClipDistanceShader1,
198                                         ESSL100_APPLEClipDistanceShader2)));
199 
200 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
201                          APPLEClipDistanceTest,
202                          Combine(Values(SH_GLES3_SPEC),
203                                  Values(sh::ESSLVersion300),
204                                  Values(ESSL300_APPLEClipDistanceShader1,
205                                         ESSL300_APPLEClipDistanceShader2)));
206 
207 }  // anonymous namespace
208