• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Use the array of inout variable with noncoherent qualifier
108 const char ESSL300_InOut7[] =
109     R"(
110     layout(noncoherent, location = 0) inout highp vec4 o_color[4];
111     uniform highp vec4 u_color;
112 
113     void main (void)
114     {
115         for (int i = 0 ; i < 4 ; i++)
116         {
117             o_color[i] = clamp(o_color[i] + u_color, vec4(0.0f), vec4(1.0f));
118         }
119     })";
120 
121 class EXTShaderFramebufferFetchNoncoherentTest : public sh::ShaderExtensionTest
122 {
123   public:
SetUp()124     void SetUp() override
125     {
126         std::map<ShShaderOutput, std::string> shaderOutputList = {
127             {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"},
128 #if defined(ANGLE_ENABLE_VULKAN)
129             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}
130 #endif
131         };
132 
133         Initialize(shaderOutputList);
134     }
135 
TearDown()136     void TearDown() override
137     {
138         for (auto shaderOutputType : mShaderOutputList)
139         {
140             DestroyCompiler(shaderOutputType.first);
141         }
142     }
143 
Initialize(std::map<ShShaderOutput,std::string> & shaderOutputList)144     void Initialize(std::map<ShShaderOutput, std::string> &shaderOutputList)
145     {
146         mShaderOutputList = std::move(shaderOutputList);
147 
148         for (auto shaderOutputType : mShaderOutputList)
149         {
150             sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]);
151             mCompilerList[shaderOutputType.first] = nullptr;
152         }
153     }
154 
DestroyCompiler(ShShaderOutput shaderOutputType)155     void DestroyCompiler(ShShaderOutput shaderOutputType)
156     {
157         if (mCompilerList[shaderOutputType])
158         {
159             sh::Destruct(mCompilerList[shaderOutputType]);
160             mCompilerList[shaderOutputType] = nullptr;
161         }
162     }
163 
InitializeCompiler()164     void InitializeCompiler()
165     {
166         for (auto shaderOutputType : mShaderOutputList)
167         {
168             InitializeCompiler(shaderOutputType.first);
169         }
170     }
171 
InitializeCompiler(ShShaderOutput shaderOutputType)172     void InitializeCompiler(ShShaderOutput shaderOutputType)
173     {
174         DestroyCompiler(shaderOutputType);
175 
176         mCompilerList[shaderOutputType] =
177             sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType,
178                                   &mResourceList[shaderOutputType]);
179         ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr)
180             << "Compiler for " << mShaderOutputList[shaderOutputType]
181             << " could not be constructed.";
182     }
183 
TestShaderCompile(ShShaderOutput shaderOutputType,const char * pragma)184     testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, const char *pragma)
185     {
186         const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
187                                        testing::get<2>(GetParam())};
188 
189         bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3,
190                                    SH_VARIABLES | SH_OBJECT_CODE);
191         if (success)
192         {
193             return ::testing::AssertionSuccess()
194                    << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
195         }
196         return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
197     }
198 
TestShaderCompile(bool expectation,const char * pragma)199     void TestShaderCompile(bool expectation, const char *pragma)
200     {
201         for (auto shaderOutputType : mShaderOutputList)
202         {
203             if (expectation)
204             {
205                 EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma));
206             }
207             else
208             {
209                 EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma));
210             }
211         }
212     }
213 
SetExtensionEnable(bool enable)214     void SetExtensionEnable(bool enable)
215     {
216         for (auto shaderOutputType : mShaderOutputList)
217         {
218             mResourceList[shaderOutputType.first].MaxDrawBuffers = 8;
219             mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
220                 enable;
221         }
222     }
223 
224   private:
225     std::map<ShShaderOutput, std::string> mShaderOutputList;
226     std::map<ShShaderOutput, ShHandle> mCompilerList;
227     std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
228 };
229 
230 class EXTShaderFramebufferFetchNoncoherentES100Test
231     : public EXTShaderFramebufferFetchNoncoherentTest
232 {};
233 
234 // Extension flag is required to compile properly. Expect failure when it is
235 // not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test,CompileFailsWithoutExtension)236 TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithoutExtension)
237 {
238     SetExtensionEnable(false);
239     InitializeCompiler();
240     TestShaderCompile(false, EXTPragma);
241 }
242 
243 // Extension directive is required to compile properly. Expect failure when
244 // it is not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test,CompileFailsWithExtensionWithoutPragma)245 TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithExtensionWithoutPragma)
246 {
247     SetExtensionEnable(true);
248     InitializeCompiler();
249     TestShaderCompile(false, "");
250 }
251 
252 class EXTShaderFramebufferFetchNoncoherentES300Test
253     : public EXTShaderFramebufferFetchNoncoherentTest
254 {};
255 
256 // Extension flag is required to compile properly. Expect failure when it is
257 // not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test,CompileFailsWithoutExtension)258 TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithoutExtension)
259 {
260     SetExtensionEnable(false);
261     InitializeCompiler();
262     TestShaderCompile(false, EXTPragma);
263 }
264 
265 // Extension directive is required to compile properly. Expect failure when
266 // it is not present.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test,CompileFailsWithExtensionWithoutPragma)267 TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithExtensionWithoutPragma)
268 {
269     SetExtensionEnable(true);
270     InitializeCompiler();
271     TestShaderCompile(false, "");
272 }
273 
274 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
275                          EXTShaderFramebufferFetchNoncoherentES100Test,
276                          Combine(Values(SH_GLES2_SPEC),
277                                  Values(sh::ESSLVersion100),
278                                  Values(ESSL100_LastFragDataRedeclared1)));
279 
280 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
281                          EXTShaderFramebufferFetchNoncoherentES300Test,
282                          Combine(Values(SH_GLES3_SPEC),
283                                  Values(sh::ESSLVersion300),
284                                  Values(ESSL300_InOut,
285                                         ESSL300_InOut2,
286                                         ESSL300_InOut3,
287                                         ESSL300_InOut4,
288                                         ESSL300_InOut5,
289                                         ESSL300_InOut6,
290                                         ESSL300_InOut7)));
291 
292 #if defined(ANGLE_ENABLE_VULKAN)
293 
294 // Use gl_LastFragData without redeclaration of gl_LastFragData with noncoherent qualifier
295 const char ESSL100_LastFragDataWithoutRedeclaration[] =
296     R"(
297     uniform highp vec4 u_color;
298 
299     void main (void)
300     {
301         gl_FragColor = u_color + gl_LastFragData[0];
302     })";
303 
304 // Redeclare gl_LastFragData without noncoherent qualifier
305 const char ESSL100_LastFragDataRedeclaredWithoutNoncoherent[] =
306     R"(
307     uniform highp vec4 u_color;
308     highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
309 
310     void main (void)
311     {
312         gl_FragColor = u_color + gl_LastFragData[0];
313     })";
314 
315 // Use inout variable without noncoherent qualifier
316 const char ESSL300_InOutWithoutNoncoherent[] =
317     R"(
318     layout(location = 0) inout highp vec4 o_color;
319     uniform highp vec4 u_color;
320 
321     void main (void)
322     {
323         o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f));
324     })";
325 
326 class EXTShaderFramebufferFetchNoncoherentSuccessTest
327     : public EXTShaderFramebufferFetchNoncoherentTest
328 {
329   public:
SetUp()330     void SetUp() override
331     {
332         std::map<ShShaderOutput, std::string> shaderOutputList = {
333             {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
334 
335         Initialize(shaderOutputList);
336     }
337 };
338 
339 class EXTShaderFramebufferFetchNoncoherentFailureTest
340     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
341 {};
342 
343 class EXTShaderFramebufferFetchNoncoherentES100SuccessTest
344     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
345 {};
346 
347 class EXTShaderFramebufferFetchNoncoherentES100FailureTest
348     : public EXTShaderFramebufferFetchNoncoherentFailureTest
349 {};
350 
351 // With extension flag and extension directive, compiling succeeds.
352 // Also test that the extension directive state is reset correctly.
TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest,CompileSucceedsWithExtensionAndPragma)353 TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest, CompileSucceedsWithExtensionAndPragma)
354 {
355     SetExtensionEnable(true);
356     InitializeCompiler();
357     TestShaderCompile(true, EXTPragma);
358     // Test reset functionality.
359     TestShaderCompile(false, "");
360     TestShaderCompile(true, EXTPragma);
361 }
362 
363 //
TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest,CompileFailsWithoutNoncoherent)364 TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest, CompileFailsWithoutNoncoherent)
365 {
366     SetExtensionEnable(true);
367     InitializeCompiler();
368     TestShaderCompile(false, EXTPragma);
369 }
370 
371 class EXTShaderFramebufferFetchNoncoherentES300SuccessTest
372     : public EXTShaderFramebufferFetchNoncoherentSuccessTest
373 {};
374 
375 class EXTShaderFramebufferFetchNoncoherentES300FailureTest
376     : public EXTShaderFramebufferFetchNoncoherentFailureTest
377 {};
378 
379 // With extension flag and extension directive, compiling succeeds.
380 // Also test that the extension directive state is reset correctly.
TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest,CompileSucceedsWithExtensionAndPragma)381 TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest, CompileSucceedsWithExtensionAndPragma)
382 {
383     SetExtensionEnable(true);
384     InitializeCompiler();
385     TestShaderCompile(true, EXTPragma);
386     // Test reset functionality.
387     TestShaderCompile(false, "");
388     TestShaderCompile(true, EXTPragma);
389 }
390 
391 //
TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest,CompileFailsWithoutNoncoherent)392 TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest, CompileFailsWithoutNoncoherent)
393 {
394     SetExtensionEnable(true);
395     InitializeCompiler();
396     TestShaderCompile(false, EXTPragma);
397 }
398 
399 // The SL #version 100 shaders that are correct work similarly
400 // in both GL2 and GL3, with and without the version string.
401 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
402                          EXTShaderFramebufferFetchNoncoherentES100SuccessTest,
403                          Combine(Values(SH_GLES2_SPEC),
404                                  Values(sh::ESSLVersion100),
405                                  Values(ESSL100_LastFragDataRedeclared1)));
406 
407 INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
408                          EXTShaderFramebufferFetchNoncoherentES100FailureTest,
409                          Combine(Values(SH_GLES2_SPEC),
410                                  Values(sh::ESSLVersion100),
411                                  Values(ESSL100_LastFragDataWithoutRedeclaration,
412                                         ESSL100_LastFragDataRedeclaredWithoutNoncoherent)));
413 
414 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
415                          EXTShaderFramebufferFetchNoncoherentES300SuccessTest,
416                          Combine(Values(SH_GLES3_SPEC),
417                                  Values(sh::ESSLVersion300),
418                                  Values(ESSL300_InOut,
419                                         ESSL300_InOut2,
420                                         ESSL300_InOut3,
421                                         ESSL300_InOut4,
422                                         ESSL300_InOut5,
423                                         ESSL300_InOut6,
424                                         ESSL300_InOut7)));
425 
426 INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
427                          EXTShaderFramebufferFetchNoncoherentES300FailureTest,
428                          Combine(Values(SH_GLES3_SPEC),
429                                  Values(sh::ESSLVersion300),
430                                  Values(ESSL300_InOutWithoutNoncoherent)));
431 #endif
432 
433 }  // anonymous namespace
434