• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2021 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 // KHR_blend_equation_advanced_test.cpp:
7 //   Test for KHR_blend_equation_advanced and KHR_blend_equation_advanced_coherent
8 //
9 
10 #include "tests/test_utils/ShaderExtensionTest.h"
11 
12 #include "common/PackedEnums.h"
13 
14 namespace
15 {
16 const char EXTPragma[] =
17     "#extension GL_KHR_blend_equation_advanced : require\n"
18     "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
19 
20 // Use the multiply equation for blending
21 const char ESSL310_Simple[] =
22     R"(
23     precision highp float;
24 
25     layout (blend_support_multiply) out;
26     layout (location = 0) out vec4 oCol;
27 
28     uniform vec4 uSrcCol;
29 
30     void main (void)
31     {
32         oCol = uSrcCol;
33     })";
34 
35 const char ESSL310_DeclaredMultiplyScreenSeparately[] =
36     R"(
37     precision highp float;
38 
39     layout (blend_support_multiply) out;
40     layout (blend_support_screen) out;
41     layout (location = 0) out vec4 oCol;
42 
43     uniform vec4 uSrcCol;
44 
45     void main (void)
46     {
47         oCol = uSrcCol;
48     })";
49 
50 const char ESSL310_DeclaredMultiplyScreenSuccessively[] =
51     R"(
52     precision highp float;
53 
54     layout (blend_support_multiply, blend_support_screen) out;
55     layout (location = 0) out vec4 oCol;
56 
57     uniform vec4 uSrcCol;
58 
59     void main (void)
60     {
61         oCol = uSrcCol;
62     })";
63 
64 const char ESSL310_With_FramebufferFetch[] =
65     R"(
66     precision highp float;
67 
68     layout (blend_support_multiply) out;
69     layout (location = 0, noncoherent) inout vec4 oCol;
70 
71     uniform vec4 uSrcCol;
72 
73     void main (void)
74     {
75         oCol = mix(oCol, uSrcCol, 0.5f);
76     })";
77 
78 const char ESSL310_With_FramebufferFetchVec3[] =
79     R"(
80     precision highp float;
81 
82     layout (blend_support_multiply) out;
83     layout (location = 0, noncoherent) inout vec3 oCol;
84 
85     uniform vec3 uSrcCol;
86 
87     void main (void)
88     {
89         oCol = mix(oCol, uSrcCol, 0.5f);
90     })";
91 
92 class KHRBlendEquationAdvancedTest : public sh::ShaderExtensionTest
93 {
94   public:
SetUp()95     void SetUp() override
96     {
97         std::map<ShShaderOutput, std::string> shaderOutputList = {
98             {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"},
99 #if defined(ANGLE_ENABLE_VULKAN)
100             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}
101 #endif
102         };
103 
104         Initialize(shaderOutputList);
105     }
106 
TearDown()107     void TearDown() override
108     {
109         for (auto shaderOutputType : mShaderOutputList)
110         {
111             DestroyCompiler(shaderOutputType.first);
112         }
113     }
114 
Initialize(std::map<ShShaderOutput,std::string> & shaderOutputList)115     void Initialize(std::map<ShShaderOutput, std::string> &shaderOutputList)
116     {
117         mShaderOutputList = std::move(shaderOutputList);
118 
119         for (auto shaderOutputType : mShaderOutputList)
120         {
121             sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]);
122             mCompilerList[shaderOutputType.first] = nullptr;
123         }
124     }
125 
DestroyCompiler(ShShaderOutput shaderOutputType)126     void DestroyCompiler(ShShaderOutput shaderOutputType)
127     {
128         if (mCompilerList[shaderOutputType])
129         {
130             sh::Destruct(mCompilerList[shaderOutputType]);
131             mCompilerList[shaderOutputType] = nullptr;
132         }
133     }
134 
InitializeCompiler()135     void InitializeCompiler()
136     {
137         for (auto shaderOutputType : mShaderOutputList)
138         {
139             InitializeCompiler(shaderOutputType.first);
140         }
141     }
142 
InitializeCompiler(ShShaderOutput shaderOutputType)143     void InitializeCompiler(ShShaderOutput shaderOutputType)
144     {
145         DestroyCompiler(shaderOutputType);
146 
147         mCompilerList[shaderOutputType] =
148             sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType,
149                                   &mResourceList[shaderOutputType]);
150         ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr)
151             << "Compiler for " << mShaderOutputList[shaderOutputType]
152             << " could not be constructed.";
153     }
154 
155     enum class Emulation
156     {
157         Disabled,
158         Enabled
159     };
160 
TestShaderCompile(ShShaderOutput shaderOutputType,const char * pragma,Emulation emulate)161     testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType,
162                                                const char *pragma,
163                                                Emulation emulate)
164     {
165         const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
166                                        testing::get<2>(GetParam())};
167 
168         ShCompileOptions compileFlags = SH_VARIABLES | SH_OBJECT_CODE;
169         if (emulate == Emulation::Enabled)
170         {
171             compileFlags |= SH_ADD_ADVANCED_BLEND_EQUATIONS_EMULATION;
172         }
173 
174         bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3, compileFlags);
175         if (success)
176         {
177             return ::testing::AssertionSuccess()
178                    << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
179         }
180         return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
181     }
182 
TestShaderCompile(bool expectation,const char * pragma,Emulation emulate)183     void TestShaderCompile(bool expectation, const char *pragma, Emulation emulate)
184     {
185         for (auto shaderOutputType : mShaderOutputList)
186         {
187             if (expectation)
188             {
189                 EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma, emulate));
190             }
191             else
192             {
193                 EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma, emulate));
194             }
195         }
196     }
197 
SetExtensionEnable(bool enable)198     void SetExtensionEnable(bool enable)
199     {
200         for (auto shaderOutputType : mShaderOutputList)
201         {
202             mResourceList[shaderOutputType.first].KHR_blend_equation_advanced = enable;
203             mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
204                 enable;
205         }
206     }
207 
208   protected:
209     std::map<ShShaderOutput, std::string> mShaderOutputList;
210     std::map<ShShaderOutput, ShHandle> mCompilerList;
211     std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
212 };
213 
214 class KHRBlendEquationAdvancedES310Test : public KHRBlendEquationAdvancedTest
215 {};
216 
217 // Extension flag is required to compile properly. Expect failure when it is not present.
TEST_P(KHRBlendEquationAdvancedES310Test,CompileFailsWithoutExtension)218 TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithoutExtension)
219 {
220     SetExtensionEnable(false);
221     InitializeCompiler();
222     TestShaderCompile(false, EXTPragma, Emulation::Disabled);
223 }
224 
225 // Extension directive is required to compile properly. Expect failure when it is not present.
TEST_P(KHRBlendEquationAdvancedES310Test,CompileFailsWithExtensionWithoutPragma)226 TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithExtensionWithoutPragma)
227 {
228     SetExtensionEnable(true);
229     InitializeCompiler();
230     TestShaderCompile(false, "", Emulation::Disabled);
231 }
232 
233 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
234                          KHRBlendEquationAdvancedES310Test,
235                          Combine(Values(SH_GLES3_1_SPEC),
236                                  Values(sh::ESSLVersion310),
237                                  Values(ESSL310_Simple,
238                                         ESSL310_With_FramebufferFetch,
239                                         ESSL310_With_FramebufferFetchVec3,
240                                         ESSL310_DeclaredMultiplyScreenSeparately,
241                                         ESSL310_DeclaredMultiplyScreenSuccessively)));
242 
243 #if defined(ANGLE_ENABLE_VULKAN)
244 
245 class KHRBlendEquationAdvancedSuccessTest : public KHRBlendEquationAdvancedTest
246 {
247   public:
SetUp()248     void SetUp() override
249     {
250         std::map<ShShaderOutput, std::string> shaderOutputList = {
251             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
252 
253         Initialize(shaderOutputList);
254     }
255 };
256 
257 class KHRBlendEquationAdvancedES310SuccessTest : public KHRBlendEquationAdvancedSuccessTest
258 {};
259 
260 // With extension flag and extension directive, compiling succeeds.  Also test that the extension
261 // directive state is reset correctly.
TEST_P(KHRBlendEquationAdvancedES310SuccessTest,CompileSucceedsWithExtensionAndPragma)262 TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragma)
263 {
264     SetExtensionEnable(true);
265     InitializeCompiler();
266     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
267     // Test reset functionality.
268     TestShaderCompile(false, "", Emulation::Disabled);
269     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
270 }
271 
272 // Same as CompileSucceedsWithExtensionAndPragma but with emulation.
TEST_P(KHRBlendEquationAdvancedES310SuccessTest,CompileSucceedsWithExtensionAndPragmaWithEmulation)273 TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragmaWithEmulation)
274 {
275     SetExtensionEnable(true);
276     InitializeCompiler();
277     TestShaderCompile(true, EXTPragma, Emulation::Enabled);
278 }
279 
280 // The SL #version 100 shaders that are correct work similarly
281 // in both GL2 and GL3, with and without the version string.
282 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
283                          KHRBlendEquationAdvancedES310SuccessTest,
284                          Combine(Values(SH_GLES3_1_SPEC),
285                                  Values(sh::ESSLVersion310),
286                                  Values(ESSL310_Simple,
287                                         ESSL310_With_FramebufferFetch,
288                                         ESSL310_With_FramebufferFetchVec3,
289                                         ESSL310_DeclaredMultiplyScreenSeparately,
290                                         ESSL310_DeclaredMultiplyScreenSuccessively)));
291 
292 class KHRBlendEquationAdvancedEnabledListCheckTest : public KHRBlendEquationAdvancedTest
293 {
294   public:
SetUp()295     void SetUp() override
296     {
297         std::map<ShShaderOutput, std::string> shaderOutputList = {
298             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
299 
300         Initialize(shaderOutputList);
301     }
302 
GetCompilerHandle(const ShShaderOutput outputType) const303     const ShHandle &GetCompilerHandle(const ShShaderOutput outputType) const
304     {
305         return mCompilerList.at(outputType);
306     }
307 };
308 
309 class KHRBlendEquationAdvancedEnabledSeparatelyTest
310     : public KHRBlendEquationAdvancedEnabledListCheckTest
311 {};
312 
313 // Test for declaring different blend equations in separate layout declarations
TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest,DeclaredEquationSeparately)314 TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparately)
315 {
316     SetExtensionEnable(true);
317     InitializeCompiler();
318     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
319 
320     const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
321     gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
322     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
323     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
324 }
325 
326 // Same as DeclaredEquationSeparately but with emulation.
TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest,DeclaredEquationSeparatelyWithEmulation)327 TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparatelyWithEmulation)
328 {
329     SetExtensionEnable(true);
330     InitializeCompiler();
331     TestShaderCompile(true, EXTPragma, Emulation::Enabled);
332 }
333 
334 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
335                          KHRBlendEquationAdvancedEnabledSeparatelyTest,
336                          Combine(Values(SH_GLES3_1_SPEC),
337                                  Values(sh::ESSLVersion310),
338                                  Values(ESSL310_DeclaredMultiplyScreenSeparately)));
339 
340 class KHRBlendEquationAdvancedEnabledSuccessivelyTest
341     : public KHRBlendEquationAdvancedEnabledListCheckTest
342 {};
343 
344 // Test for declaring different blend equations in the same layout declaration
TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest,DeclaredEquationSuccessively)345 TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest, DeclaredEquationSuccessively)
346 {
347     SetExtensionEnable(true);
348     InitializeCompiler();
349     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
350 
351     const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
352     gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
353     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
354     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
355 }
356 
357 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
358                          KHRBlendEquationAdvancedEnabledSuccessivelyTest,
359                          Combine(Values(SH_GLES3_1_SPEC),
360                                  Values(sh::ESSLVersion310),
361                                  Values(ESSL310_DeclaredMultiplyScreenSuccessively)));
362 
363 #endif
364 
365 }  // anonymous namespace
366