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 class APPLEClipDistanceTest : public sh::ShaderExtensionTest
46 {
47 public:
InitializeCompiler()48 void InitializeCompiler() { InitializeCompiler(SH_GLSL_130_OUTPUT); }
InitializeCompiler(ShShaderOutput shaderOutputType)49 void InitializeCompiler(ShShaderOutput shaderOutputType)
50 {
51 DestroyCompiler();
52
53 mCompiler = sh::ConstructCompiler(GL_VERTEX_SHADER, testing::get<0>(GetParam()),
54 shaderOutputType, &mResources);
55 ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
56 }
57
TestShaderCompile(const char * pragma)58 testing::AssertionResult TestShaderCompile(const char *pragma)
59 {
60 const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
61 testing::get<2>(GetParam())};
62 bool success = sh::Compile(mCompiler, shaderStrings, 3, SH_VARIABLES | SH_OBJECT_CODE);
63 if (success)
64 {
65 return ::testing::AssertionSuccess() << "Compilation success";
66 }
67 return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
68 }
69 };
70
71 // Extension flag is required to compile properly. Expect failure when it is
72 // not present.
TEST_P(APPLEClipDistanceTest,CompileFailsWithoutExtension)73 TEST_P(APPLEClipDistanceTest, CompileFailsWithoutExtension)
74 {
75 mResources.APPLE_clip_distance = 0;
76 InitializeCompiler();
77 EXPECT_FALSE(TestShaderCompile(EXTPragma));
78 }
79
80 // Extension directive is required to compile properly. Expect failure when
81 // it is not present.
TEST_P(APPLEClipDistanceTest,CompileFailsWithExtensionWithoutPragma)82 TEST_P(APPLEClipDistanceTest, CompileFailsWithExtensionWithoutPragma)
83 {
84 mResources.APPLE_clip_distance = 1;
85 InitializeCompiler();
86 EXPECT_FALSE(TestShaderCompile(""));
87 }
88
89 // With extension flag and extension directive, compiling succeeds.
90 // Also test that the extension directive state is reset correctly.
TEST_P(APPLEClipDistanceTest,CompileSucceedsWithExtensionAndPragma)91 TEST_P(APPLEClipDistanceTest, CompileSucceedsWithExtensionAndPragma)
92 {
93 mResources.APPLE_clip_distance = 1;
94 mResources.MaxClipDistances = 8;
95 InitializeCompiler();
96 EXPECT_TRUE(TestShaderCompile(EXTPragma));
97 // Test reset functionality.
98 EXPECT_FALSE(TestShaderCompile(""));
99 EXPECT_TRUE(TestShaderCompile(EXTPragma));
100 }
101
102 #if defined(ANGLE_ENABLE_VULKAN)
103 // With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(APPLEClipDistanceTest,CompileSucceedsVulkan)104 TEST_P(APPLEClipDistanceTest, CompileSucceedsVulkan)
105 {
106 mResources.APPLE_clip_distance = 1;
107 mResources.MaxClipDistances = 8;
108
109 InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
110 EXPECT_TRUE(TestShaderCompile(EXTPragma));
111 }
112 #endif
113
114 #if defined(ANGLE_ENABLE_METAL)
115 // With extension flag and extension directive, compiling using TranslatorMetal succeeds.
TEST_P(APPLEClipDistanceTest,CompileSucceedsMetal)116 TEST_P(APPLEClipDistanceTest, CompileSucceedsMetal)
117 {
118 mResources.APPLE_clip_distance = 1;
119 mResources.MaxClipDistances = 8;
120
121 InitializeCompiler(SH_SPIRV_METAL_OUTPUT);
122 EXPECT_TRUE(TestShaderCompile(EXTPragma));
123 }
124 #endif
125
126 // The SL #version 100 shaders that are correct work similarly
127 // in both GL2 and GL3, with and without the version string.
128 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
129 APPLEClipDistanceTest,
130 Combine(Values(SH_GLES2_SPEC),
131 Values(sh::ESSLVersion100),
132 Values(ESSL100_APPLEClipDistanceShader1,
133 ESSL100_APPLEClipDistanceShader2)));
134
135 } // anonymous namespace
136