xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 = {};
169         compileFlags.objectCode       = true;
170         if (emulate == Emulation::Enabled)
171         {
172             compileFlags.addAdvancedBlendEquationsEmulation = true;
173         }
174 
175         bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3, compileFlags);
176         if (success)
177         {
178             return ::testing::AssertionSuccess()
179                    << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
180         }
181         return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
182     }
183 
TestShaderCompile(bool expectation,const char * pragma,Emulation emulate)184     void TestShaderCompile(bool expectation, const char *pragma, Emulation emulate)
185     {
186         for (auto shaderOutputType : mShaderOutputList)
187         {
188             if (expectation)
189             {
190                 EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma, emulate));
191             }
192             else
193             {
194                 EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma, emulate));
195             }
196         }
197     }
198 
SetExtensionEnable(bool enable)199     void SetExtensionEnable(bool enable)
200     {
201         for (auto shaderOutputType : mShaderOutputList)
202         {
203             mResourceList[shaderOutputType.first].KHR_blend_equation_advanced = enable;
204             mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
205                 enable;
206         }
207     }
208 
209   protected:
210     std::map<ShShaderOutput, std::string> mShaderOutputList;
211     std::map<ShShaderOutput, ShHandle> mCompilerList;
212     std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
213 };
214 
215 class KHRBlendEquationAdvancedES310Test : public KHRBlendEquationAdvancedTest
216 {};
217 
218 // Extension flag is required to compile properly. Expect failure when it is not present.
TEST_P(KHRBlendEquationAdvancedES310Test,CompileFailsWithoutExtension)219 TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithoutExtension)
220 {
221     SetExtensionEnable(false);
222     InitializeCompiler();
223     TestShaderCompile(false, EXTPragma, Emulation::Disabled);
224 }
225 
226 // Extension directive is required to compile properly. Expect failure when it is not present.
TEST_P(KHRBlendEquationAdvancedES310Test,CompileFailsWithExtensionWithoutPragma)227 TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithExtensionWithoutPragma)
228 {
229     SetExtensionEnable(true);
230     InitializeCompiler();
231     TestShaderCompile(false, "", Emulation::Disabled);
232 }
233 
234 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
235                          KHRBlendEquationAdvancedES310Test,
236                          Combine(Values(SH_GLES3_1_SPEC),
237                                  Values(sh::ESSLVersion310),
238                                  Values(ESSL310_Simple,
239                                         ESSL310_With_FramebufferFetch,
240                                         ESSL310_With_FramebufferFetchVec3,
241                                         ESSL310_DeclaredMultiplyScreenSeparately,
242                                         ESSL310_DeclaredMultiplyScreenSuccessively)));
243 
244 #if defined(ANGLE_ENABLE_VULKAN)
245 
246 class KHRBlendEquationAdvancedSuccessTest : public KHRBlendEquationAdvancedTest
247 {
248   public:
SetUp()249     void SetUp() override
250     {
251         std::map<ShShaderOutput, std::string> shaderOutputList = {
252             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
253 
254         Initialize(shaderOutputList);
255     }
256 };
257 
258 class KHRBlendEquationAdvancedES310SuccessTest : public KHRBlendEquationAdvancedSuccessTest
259 {};
260 
261 // With extension flag and extension directive, compiling succeeds.  Also test that the extension
262 // directive state is reset correctly.
TEST_P(KHRBlendEquationAdvancedES310SuccessTest,CompileSucceedsWithExtensionAndPragma)263 TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragma)
264 {
265     SetExtensionEnable(true);
266     InitializeCompiler();
267     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
268     // Test reset functionality.
269     TestShaderCompile(false, "", Emulation::Disabled);
270     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
271 }
272 
273 // Same as CompileSucceedsWithExtensionAndPragma but with emulation.
TEST_P(KHRBlendEquationAdvancedES310SuccessTest,CompileSucceedsWithExtensionAndPragmaWithEmulation)274 TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragmaWithEmulation)
275 {
276     SetExtensionEnable(true);
277     InitializeCompiler();
278     TestShaderCompile(true, EXTPragma, Emulation::Enabled);
279 }
280 
281 // The SL #version 100 shaders that are correct work similarly
282 // in both GL2 and GL3, with and without the version string.
283 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
284                          KHRBlendEquationAdvancedES310SuccessTest,
285                          Combine(Values(SH_GLES3_1_SPEC),
286                                  Values(sh::ESSLVersion310),
287                                  Values(ESSL310_Simple,
288                                         ESSL310_With_FramebufferFetch,
289                                         ESSL310_With_FramebufferFetchVec3,
290                                         ESSL310_DeclaredMultiplyScreenSeparately,
291                                         ESSL310_DeclaredMultiplyScreenSuccessively)));
292 
293 class KHRBlendEquationAdvancedEnabledListCheckTest : public KHRBlendEquationAdvancedTest
294 {
295   public:
SetUp()296     void SetUp() override
297     {
298         std::map<ShShaderOutput, std::string> shaderOutputList = {
299             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
300 
301         Initialize(shaderOutputList);
302     }
303 
GetCompilerHandle(const ShShaderOutput outputType) const304     const ShHandle &GetCompilerHandle(const ShShaderOutput outputType) const
305     {
306         return mCompilerList.at(outputType);
307     }
308 };
309 
310 class KHRBlendEquationAdvancedEnabledSeparatelyTest
311     : public KHRBlendEquationAdvancedEnabledListCheckTest
312 {};
313 
314 // Test for declaring different blend equations in separate layout declarations
TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest,DeclaredEquationSeparately)315 TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparately)
316 {
317     SetExtensionEnable(true);
318     InitializeCompiler();
319     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
320 
321     const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
322     gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
323     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
324     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
325 }
326 
327 // Same as DeclaredEquationSeparately but with emulation.
TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest,DeclaredEquationSeparatelyWithEmulation)328 TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparatelyWithEmulation)
329 {
330     SetExtensionEnable(true);
331     InitializeCompiler();
332     TestShaderCompile(true, EXTPragma, Emulation::Enabled);
333 }
334 
335 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
336                          KHRBlendEquationAdvancedEnabledSeparatelyTest,
337                          Combine(Values(SH_GLES3_1_SPEC),
338                                  Values(sh::ESSLVersion310),
339                                  Values(ESSL310_DeclaredMultiplyScreenSeparately)));
340 
341 class KHRBlendEquationAdvancedEnabledSuccessivelyTest
342     : public KHRBlendEquationAdvancedEnabledListCheckTest
343 {};
344 
345 // Test for declaring different blend equations in the same layout declaration
TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest,DeclaredEquationSuccessively)346 TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest, DeclaredEquationSuccessively)
347 {
348     SetExtensionEnable(true);
349     InitializeCompiler();
350     TestShaderCompile(true, EXTPragma, Emulation::Disabled);
351 
352     const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
353     gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
354     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
355     EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
356 }
357 
358 INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
359                          KHRBlendEquationAdvancedEnabledSuccessivelyTest,
360                          Combine(Values(SH_GLES3_1_SPEC),
361                                  Values(sh::ESSLVersion310),
362                                  Values(ESSL310_DeclaredMultiplyScreenSuccessively)));
363 
364 #endif
365 
366 }  // anonymous namespace
367