xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/EXT_shader_framebuffer_fetch_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 // EXT_shader_framebuffer_fetch_test.cpp:
7 //   Test for EXT_shader_framebuffer_fetch and EXT_shader_framebuffer_fetch_non_coherent
8 //
9 
10 #include "tests/test_utils/ShaderExtensionTest.h"
11 
12 namespace
13 {
14 const char EXTPragma[] = "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
15 
16 // Redeclare gl_LastFragData with noncoherent qualifier
17 const char ESSL100_LastFragDataRedeclared1[] =
18     R"(
19     uniform highp vec4 u_color;
20     layout(noncoherent) highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
21 
22     void main (void)
23     {
24         gl_FragColor = u_color + gl_LastFragData[0] + gl_LastFragData[2];
25     })";
26 
27 // Use inout variable with noncoherent qualifier
28 const char ESSL300_InOut[] =
29     R"(
30     layout(noncoherent, location = 0) inout highp vec4 o_color;
31     uniform highp vec4 u_color;
32 
33     void main (void)
34     {
35         o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f));
36     })";
37 
38 // Use inout variable with noncoherent qualifier and 3-components vector
39 const char ESSL300_InOut2[] =
40     R"(
41     layout(noncoherent, location = 0) inout highp vec3 o_color;
42     uniform highp vec3 u_color;
43 
44     void main (void)
45     {
46         o_color = clamp(o_color + u_color, vec3(0.0f), vec3(1.0f));
47     })";
48 
49 // Use inout variable with noncoherent qualifier and integer type qualifier
50 const char ESSL300_InOut3[] =
51     R"(
52     layout(noncoherent, location = 0) inout highp ivec4 o_color;
53     uniform highp ivec4 u_color;
54 
55     void main (void)
56     {
57         o_color = clamp(o_color + u_color, ivec4(0), ivec4(1));
58     })";
59 
60 // Use inout variable with noncoherent qualifier and unsigned integer type qualifier
61 const char ESSL300_InOut4[] =
62     R"(
63     layout(noncoherent, location = 0) inout highp uvec4 o_color;
64     uniform highp uvec4 u_color;
65 
66     void main (void)
67     {
68         o_color = clamp(o_color + u_color, uvec4(0), uvec4(1));
69     })";
70 
71 // Use inout variable with noncoherent qualifier and inout function parameter
72 const char ESSL300_InOut5[] =
73     R"(
74     layout(noncoherent, location = 0) inout highp vec4 o_color;
75     uniform highp vec4 u_color;
76 
77     void getClampValue(inout highp mat4 io_color, highp vec4 i_color)
78     {
79         io_color[0] = clamp(io_color[0] + i_color, vec4(0.0f), vec4(1.0f));
80     }
81 
82     void main (void)
83     {
84         highp mat4 o_color_mat = mat4(0);
85         o_color_mat[0] = o_color;
86         getClampValue(o_color_mat, u_color);
87         o_color = o_color_mat[0];
88     })";
89 
90 // Use multiple inout variables with noncoherent qualifier
91 const char ESSL300_InOut6[] =
92     R"(
93     layout(noncoherent, location = 0) inout highp vec4 o_color0;
94     layout(noncoherent, location = 1) inout highp vec4 o_color1;
95     layout(noncoherent, location = 2) inout highp vec4 o_color2;
96     layout(noncoherent, location = 3) inout highp vec4 o_color3;
97     uniform highp vec4 u_color;
98 
99     void main (void)
100     {
101         o_color0 = clamp(o_color0 + u_color, vec4(0.0f), vec4(1.0f));
102         o_color1 = clamp(o_color1 + u_color, vec4(0.0f), vec4(1.0f));
103         o_color2 = clamp(o_color2 + u_color, vec4(0.0f), vec4(1.0f));
104         o_color3 = clamp(o_color3 + u_color, vec4(0.0f), vec4(1.0f));
105     })";
106 
107 class EXTShaderFramebufferFetchNoncoherentTest : public sh::ShaderExtensionTest
108 {
109   public:
SetUp()110     void SetUp() override
111     {
112         std::map<ShShaderOutput, std::string> shaderOutputList = {
113             {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"},
114 #if defined(ANGLE_ENABLE_VULKAN)
115             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}
116 #endif
117         };
118 
119         Initialize(shaderOutputList);
120     }
121 
TearDown()122     void TearDown() override
123     {
124         for (auto shaderOutputType : mShaderOutputList)
125         {
126             DestroyCompiler(shaderOutputType.first);
127         }
128     }
129 
Initialize(std::map<ShShaderOutput,std::string> & shaderOutputList)130     void Initialize(std::map<ShShaderOutput, std::string> &shaderOutputList)
131     {
132         mShaderOutputList = std::move(shaderOutputList);
133 
134         for (auto shaderOutputType : mShaderOutputList)
135         {
136             sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]);
137             mCompilerList[shaderOutputType.first] = nullptr;
138         }
139     }
140 
DestroyCompiler(ShShaderOutput shaderOutputType)141     void DestroyCompiler(ShShaderOutput shaderOutputType)
142     {
143         if (mCompilerList[shaderOutputType])
144         {
145             sh::Destruct(mCompilerList[shaderOutputType]);
146             mCompilerList[shaderOutputType] = nullptr;
147         }
148     }
149 
InitializeCompiler()150     void InitializeCompiler()
151     {
152         for (auto shaderOutputType : mShaderOutputList)
153         {
154             InitializeCompiler(shaderOutputType.first);
155         }
156     }
157 
InitializeCompiler(ShShaderOutput shaderOutputType)158     void InitializeCompiler(ShShaderOutput shaderOutputType)
159     {
160         DestroyCompiler(shaderOutputType);
161 
162         mCompilerList[shaderOutputType] =
163             sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType,
164                                   &mResourceList[shaderOutputType]);
165         ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr)
166             << "Compiler for " << mShaderOutputList[shaderOutputType]
167             << " could not be constructed.";
168     }
169 
TestShaderCompile(ShShaderOutput shaderOutputType,const char * pragma)170     testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, const char *pragma)
171     {
172         ShCompileOptions compileOptions = {};
173         compileOptions.objectCode       = true;
174 
175         const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
176                                        testing::get<2>(GetParam())};
177 
178         bool success =
179             sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3, compileOptions);
180         if (success)
181         {
182             return ::testing::AssertionSuccess()
183                    << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
184         }
185         return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
186     }
187 
TestShaderCompile(bool expectation,const char * pragma)188     void TestShaderCompile(bool expectation, const char *pragma)
189     {
190         for (auto shaderOutputType : mShaderOutputList)
191         {
192             if (expectation)
193             {
194                 EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma));
195             }
196             else
197             {
198                 EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma));
199             }
200         }
201     }
202 
SetExtensionEnable(bool enable)203     void SetExtensionEnable(bool enable)
204     {
205         for (auto shaderOutputType : mShaderOutputList)
206         {
207             mResourceList[shaderOutputType.first].MaxDrawBuffers = 8;
208             mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
209                 enable;
210         }
211     }
212 
213   private:
214     std::map<ShShaderOutput, std::string> mShaderOutputList;
215     std::map<ShShaderOutput, ShHandle> mCompilerList;
216     std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
217 };
218 
219 class EXTShaderFramebufferFetchNoncoherentES100Test
220     : public EXTShaderFramebufferFetchNoncoherentTest
221 {};
222 
223 // Extension flag is required to compile properly. Expect failure when it is
224 // not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test,CompileFailsWithoutExtension)225 TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithoutExtension)
226 {
227     SetExtensionEnable(false);
228     InitializeCompiler();
229     TestShaderCompile(false, EXTPragma);
230 }
231 
232 // Extension directive is required to compile properly. Expect failure when
233 // it is not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test,CompileFailsWithExtensionWithoutPragma)234 TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithExtensionWithoutPragma)
235 {
236     SetExtensionEnable(true);
237     InitializeCompiler();
238     TestShaderCompile(false, "");
239 }
240 
241 class EXTShaderFramebufferFetchNoncoherentES300Test
242     : public EXTShaderFramebufferFetchNoncoherentTest
243 {};
244 
245 // Extension flag is required to compile properly. Expect failure when it is
246 // not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test,CompileFailsWithoutExtension)247 TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithoutExtension)
248 {
249     SetExtensionEnable(false);
250     InitializeCompiler();
251     TestShaderCompile(false, EXTPragma);
252 }
253 
254 // Extension directive is required to compile properly. Expect failure when
255 // it is not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test,CompileFailsWithExtensionWithoutPragma)256 TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithExtensionWithoutPragma)
257 {
258     SetExtensionEnable(true);
259     InitializeCompiler();
260     TestShaderCompile(false, "");
261 }
262 
263 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
264                          EXTShaderFramebufferFetchNoncoherentES100Test,
265                          Combine(Values(SH_GLES2_SPEC),
266                                  Values(sh::ESSLVersion100),
267                                  Values(ESSL100_LastFragDataRedeclared1)));
268 
269 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
270                          EXTShaderFramebufferFetchNoncoherentES300Test,
271                          Combine(Values(SH_GLES3_SPEC),
272                                  Values(sh::ESSLVersion300),
273                                  Values(ESSL300_InOut,
274                                         ESSL300_InOut2,
275                                         ESSL300_InOut3,
276                                         ESSL300_InOut4,
277                                         ESSL300_InOut5,
278                                         ESSL300_InOut6)));
279 
280 #if defined(ANGLE_ENABLE_VULKAN)
281 
282 // Use gl_LastFragData without redeclaration of gl_LastFragData with noncoherent qualifier
283 const char ESSL100_LastFragDataWithoutRedeclaration[] =
284     R"(
285     uniform highp vec4 u_color;
286 
287     void main (void)
288     {
289         gl_FragColor = u_color + gl_LastFragData[0];
290     })";
291 
292 // Redeclare gl_LastFragData without noncoherent qualifier
293 const char ESSL100_LastFragDataRedeclaredWithoutNoncoherent[] =
294     R"(
295     uniform highp vec4 u_color;
296     highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
297 
298     void main (void)
299     {
300         gl_FragColor = u_color + gl_LastFragData[0];
301     })";
302 
303 // Use inout variable without noncoherent qualifier
304 const char ESSL300_InOutWithoutNoncoherent[] =
305     R"(
306     layout(location = 0) inout highp vec4 o_color;
307     uniform highp vec4 u_color;
308 
309     void main (void)
310     {
311         o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f));
312     })";
313 
314 class EXTShaderFramebufferFetchNoncoherentSuccessTest
315     : public EXTShaderFramebufferFetchNoncoherentTest
316 {
317   public:
SetUp()318     void SetUp() override
319     {
320         std::map<ShShaderOutput, std::string> shaderOutputList = {
321             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
322 
323         Initialize(shaderOutputList);
324     }
325 };
326 
327 class EXTShaderFramebufferFetchNoncoherentFailureTest
328     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
329 {};
330 
331 class EXTShaderFramebufferFetchNoncoherentES100SuccessTest
332     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
333 {};
334 
335 class EXTShaderFramebufferFetchNoncoherentES100FailureTest
336     : public EXTShaderFramebufferFetchNoncoherentFailureTest
337 {};
338 
339 // With extension flag and extension directive, compiling succeeds.
340 // Also test that the extension directive state is reset correctly.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest,CompileSucceedsWithExtensionAndPragma)341 TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest, CompileSucceedsWithExtensionAndPragma)
342 {
343     SetExtensionEnable(true);
344     InitializeCompiler();
345     TestShaderCompile(true, EXTPragma);
346     // Test reset functionality.
347     TestShaderCompile(false, "");
348     TestShaderCompile(true, EXTPragma);
349 }
350 
351 //
TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest,CompileFailsWithoutNoncoherent)352 TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest, CompileFailsWithoutNoncoherent)
353 {
354     SetExtensionEnable(true);
355     InitializeCompiler();
356     TestShaderCompile(false, EXTPragma);
357 }
358 
359 class EXTShaderFramebufferFetchNoncoherentES300SuccessTest
360     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
361 {};
362 
363 class EXTShaderFramebufferFetchNoncoherentES300FailureTest
364     : public EXTShaderFramebufferFetchNoncoherentFailureTest
365 {};
366 
367 // With extension flag and extension directive, compiling succeeds.
368 // Also test that the extension directive state is reset correctly.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest,CompileSucceedsWithExtensionAndPragma)369 TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest, CompileSucceedsWithExtensionAndPragma)
370 {
371     SetExtensionEnable(true);
372     InitializeCompiler();
373     TestShaderCompile(true, EXTPragma);
374     // Test reset functionality.
375     TestShaderCompile(false, "");
376     TestShaderCompile(true, EXTPragma);
377 }
378 
379 //
TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest,CompileFailsWithoutNoncoherent)380 TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest, CompileFailsWithoutNoncoherent)
381 {
382     SetExtensionEnable(true);
383     InitializeCompiler();
384     TestShaderCompile(false, EXTPragma);
385 }
386 
387 // The SL #version 100 shaders that are correct work similarly
388 // in both GL2 and GL3, with and without the version string.
389 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
390                          EXTShaderFramebufferFetchNoncoherentES100SuccessTest,
391                          Combine(Values(SH_GLES2_SPEC),
392                                  Values(sh::ESSLVersion100),
393                                  Values(ESSL100_LastFragDataRedeclared1)));
394 
395 INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
396                          EXTShaderFramebufferFetchNoncoherentES100FailureTest,
397                          Combine(Values(SH_GLES2_SPEC),
398                                  Values(sh::ESSLVersion100),
399                                  Values(ESSL100_LastFragDataWithoutRedeclaration,
400                                         ESSL100_LastFragDataRedeclaredWithoutNoncoherent)));
401 
402 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
403                          EXTShaderFramebufferFetchNoncoherentES300SuccessTest,
404                          Combine(Values(SH_GLES3_SPEC),
405                                  Values(sh::ESSLVersion300),
406                                  Values(ESSL300_InOut,
407                                         ESSL300_InOut2,
408                                         ESSL300_InOut3,
409                                         ESSL300_InOut4,
410                                         ESSL300_InOut5,
411                                         ESSL300_InOut6)));
412 
413 INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
414                          EXTShaderFramebufferFetchNoncoherentES300FailureTest,
415                          Combine(Values(SH_GLES3_SPEC),
416                                  Values(sh::ESSLVersion300),
417                                  Values(ESSL300_InOutWithoutNoncoherent)));
418 #endif
419 
420 }  // anonymous namespace
421