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