xref: /aosp_15_r20/external/angle/src/tests/gl_tests/FenceSyncTests.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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 
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 
10 using namespace angle;
11 
12 class FenceNVTest : public ANGLETest<>
13 {
14   protected:
FenceNVTest()15     FenceNVTest()
16     {
17         setWindowWidth(128);
18         setWindowHeight(128);
19         setConfigRedBits(8);
20         setConfigGreenBits(8);
21         setConfigBlueBits(8);
22         setConfigAlphaBits(8);
23         setConfigDepthBits(24);
24     }
25 };
26 
27 class FenceSyncTest : public ANGLETest<>
28 {
29   public:
30     static constexpr uint32_t kSize = 256;
31 
32   protected:
FenceSyncTest()33     FenceSyncTest()
34     {
35         setWindowWidth(kSize);
36         setWindowHeight(kSize);
37         setConfigRedBits(8);
38         setConfigGreenBits(8);
39         setConfigBlueBits(8);
40         setConfigAlphaBits(8);
41         setConfigDepthBits(24);
42     }
43 };
44 
45 // FenceNV objects should respond false to glIsFenceNV until they've been set
TEST_P(FenceNVTest,IsFence)46 TEST_P(FenceNVTest, IsFence)
47 {
48     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence"));
49 
50     GLuint fence = 0;
51     glGenFencesNV(1, &fence);
52     EXPECT_GL_NO_ERROR();
53 
54     EXPECT_GL_FALSE(glIsFenceNV(fence));
55     EXPECT_GL_NO_ERROR();
56 
57     glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
58     EXPECT_GL_NO_ERROR();
59 
60     EXPECT_GL_TRUE(glIsFenceNV(fence));
61     EXPECT_GL_NO_ERROR();
62 }
63 
64 // Test error cases for all FenceNV functions
TEST_P(FenceNVTest,Errors)65 TEST_P(FenceNVTest, Errors)
66 {
67     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence"));
68 
69     EXPECT_GL_TRUE(glTestFenceNV(10)) << "glTestFenceNV should still return TRUE for an invalid "
70                                          "fence and generate an INVALID_OPERATION";
71     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
72 
73     GLuint fence = 20;
74 
75     // glGenFencesNV should generate INVALID_VALUE for a negative n and not write anything to the
76     // fences pointer
77     glGenFencesNV(-1, &fence);
78     EXPECT_GL_ERROR(GL_INVALID_VALUE);
79     EXPECT_EQ(20u, fence);
80 
81     // Generate a real fence
82     glGenFencesNV(1, &fence);
83     EXPECT_GL_NO_ERROR();
84 
85     EXPECT_GL_TRUE(glTestFenceNV(fence)) << "glTestFenceNV should still return TRUE for a fence "
86                                             "that is not started and generate an INVALID_OPERATION";
87     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
88 
89     // glGetFenceivNV should generate an INVALID_OPERATION for an invalid or unstarted fence and not
90     // modify the params
91     GLint result = 30;
92     glGetFenceivNV(10, GL_FENCE_STATUS_NV, &result);
93     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
94     EXPECT_EQ(30, result);
95 
96     glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &result);
97     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
98     EXPECT_EQ(30, result);
99 
100     // glSetFenceNV should generate an error for any condition that is not ALL_COMPLETED_NV
101     glSetFenceNV(fence, 0);
102     EXPECT_GL_ERROR(GL_INVALID_ENUM);
103 
104     // glSetFenceNV should generate INVALID_OPERATION for an invalid fence
105     glSetFenceNV(10, GL_ALL_COMPLETED_NV);
106     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
107 }
108 
109 // Test that basic usage works and doesn't generate errors or crash
TEST_P(FenceNVTest,BasicOperations)110 TEST_P(FenceNVTest, BasicOperations)
111 {
112     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence"));
113 
114     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
115 
116     constexpr size_t kFenceCount = 20;
117     GLuint fences[kFenceCount]   = {0};
118     glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences);
119     EXPECT_GL_NO_ERROR();
120 
121     for (GLuint fence : fences)
122     {
123         glClear(GL_COLOR_BUFFER_BIT);
124         glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
125     }
126 
127     // Finish the last fence, all fences before should be marked complete
128     glFinishFenceNV(fences[kFenceCount - 1]);
129 
130     for (GLuint fence : fences)
131     {
132         GLint status = 0;
133         glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &status);
134         EXPECT_GL_NO_ERROR();
135 
136         // Fence should be complete now that Finish has been called
137         EXPECT_GL_TRUE(status);
138     }
139 
140     EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255);
141 }
142 
143 // Sync objects should respond true to IsSync after they are created with glFenceSync
TEST_P(FenceSyncTest,IsSync)144 TEST_P(FenceSyncTest, IsSync)
145 {
146     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
147     EXPECT_GL_NO_ERROR();
148 
149     EXPECT_GL_TRUE(glIsSync(sync));
150     EXPECT_GL_FALSE(glIsSync(reinterpret_cast<GLsync>(40)));
151 }
152 
153 // Test error cases for all Sync function
TEST_P(FenceSyncTest,Errors)154 TEST_P(FenceSyncTest, Errors)
155 {
156     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
157 
158     // DeleteSync generates INVALID_VALUE when the sync is not valid
159     glDeleteSync(reinterpret_cast<GLsync>(20));
160     EXPECT_GL_ERROR(GL_INVALID_VALUE);
161 
162     // glFenceSync generates GL_INVALID_ENUM if the condition is not GL_SYNC_GPU_COMMANDS_COMPLETE
163     EXPECT_EQ(0, glFenceSync(0, 0));
164     EXPECT_GL_ERROR(GL_INVALID_ENUM);
165 
166     // glFenceSync generates GL_INVALID_ENUM if the flags is not 0
167     EXPECT_EQ(0, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 10));
168     EXPECT_GL_ERROR(GL_INVALID_VALUE);
169 
170     // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if flags contains more
171     // than just GL_SYNC_FLUSH_COMMANDS_BIT
172     EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT | 0x2, 0));
173     EXPECT_GL_ERROR(GL_INVALID_VALUE);
174 
175     // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if the sync object is
176     // not valid
177     EXPECT_GLENUM_EQ(GL_WAIT_FAILED,
178                      glClientWaitSync(reinterpret_cast<GLsync>(30), GL_SYNC_FLUSH_COMMANDS_BIT, 0));
179     EXPECT_GL_ERROR(GL_INVALID_VALUE);
180 
181     // glWaitSync generates GL_INVALID_VALUE if flags is non-zero
182     glWaitSync(sync, 1, GL_TIMEOUT_IGNORED);
183     EXPECT_GL_ERROR(GL_INVALID_VALUE);
184 
185     // glWaitSync generates GL_INVALID_VALUE if GLuint64 is not GL_TIMEOUT_IGNORED
186     glWaitSync(sync, 0, 0);
187     EXPECT_GL_ERROR(GL_INVALID_VALUE);
188 
189     // glWaitSync generates GL_INVALID_VALUE if the sync object is not valid
190     glWaitSync(reinterpret_cast<GLsync>(30), 0, GL_TIMEOUT_IGNORED);
191     EXPECT_GL_ERROR(GL_INVALID_VALUE);
192 
193     // glGetSynciv generates GL_INVALID_VALUE if bufSize is less than zero, results should be
194     // untouched
195     GLsizei length = 20;
196     GLint value    = 30;
197     glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &value);
198     EXPECT_GL_ERROR(GL_INVALID_VALUE);
199     EXPECT_EQ(20, length);
200     EXPECT_EQ(30, value);
201 
202     // glGetSynciv generates GL_INVALID_VALUE if the sync object is not valid, results should be
203     // untouched
204     glGetSynciv(reinterpret_cast<GLsync>(30), GL_OBJECT_TYPE, 1, &length, &value);
205     EXPECT_GL_ERROR(GL_INVALID_VALUE);
206     EXPECT_EQ(20, length);
207     EXPECT_EQ(30, value);
208 }
209 
210 // Test usage of glGetSynciv
TEST_P(FenceSyncTest,BasicQueries)211 TEST_P(FenceSyncTest, BasicQueries)
212 {
213     GLsizei length = 0;
214     GLint value    = 0;
215     GLsync sync    = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
216 
217     glGetSynciv(sync, GL_SYNC_CONDITION, 1, &length, &value);
218     EXPECT_GL_NO_ERROR();
219     EXPECT_EQ(GL_SYNC_GPU_COMMANDS_COMPLETE, value);
220 
221     glGetSynciv(sync, GL_OBJECT_TYPE, 1, &length, &value);
222     EXPECT_GL_NO_ERROR();
223     EXPECT_EQ(GL_SYNC_FENCE, value);
224 
225     glGetSynciv(sync, GL_SYNC_FLAGS, 1, &length, &value);
226     EXPECT_GL_NO_ERROR();
227     EXPECT_EQ(0, value);
228 }
229 
230 // Test usage of glGetSynciv with nullptr as length
TEST_P(FenceSyncTest,NullLength)231 TEST_P(FenceSyncTest, NullLength)
232 {
233     GLint value = 0;
234     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
235     glGetSynciv(sync, GL_SYNC_STATUS, 1, nullptr, &value);
236     glDeleteSync(sync);
237     EXPECT_GL_NO_ERROR();
238 }
239 
240 // Test that basic usage works and doesn't generate errors or crash
TEST_P(FenceSyncTest,BasicOperations)241 TEST_P(FenceSyncTest, BasicOperations)
242 {
243     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
244 
245     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
246 
247     glClear(GL_COLOR_BUFFER_BIT);
248     glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
249     EXPECT_GL_NO_ERROR();
250 
251     GLsizei length         = 0;
252     GLint value            = 0;
253     unsigned int loopCount = 0;
254 
255     glFlush();
256 
257     // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
258     while (value != GL_SIGNALED && loopCount <= 1000000)
259     {
260         loopCount++;
261 
262         glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value);
263         ASSERT_GL_NO_ERROR();
264     }
265 
266     ASSERT_GLENUM_EQ(GL_SIGNALED, value);
267 
268     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
269     for (size_t i = 0; i < 20; i++)
270     {
271         glClear(GL_COLOR_BUFFER_BIT);
272         drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
273         ASSERT_GL_NO_ERROR();
274 
275         GLsync clientWaitSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
276         ASSERT_GL_NO_ERROR();
277 
278         // Don't wait forever to make sure the test terminates
279         constexpr GLuint64 kTimeout = 1'000'000'000;  // 1 second
280         GLenum clientWaitResult =
281             glClientWaitSync(clientWaitSync, GL_SYNC_FLUSH_COMMANDS_BIT, kTimeout);
282         EXPECT_GL_NO_ERROR();
283         EXPECT_TRUE(clientWaitResult == GL_CONDITION_SATISFIED ||
284                     clientWaitResult == GL_ALREADY_SIGNALED);
285 
286         glDeleteSync(clientWaitSync);
287         ASSERT_GL_NO_ERROR();
288     }
289 }
290 
291 // Test that multiple fences and draws can be issued
TEST_P(FenceSyncTest,MultipleFenceDraw)292 TEST_P(FenceSyncTest, MultipleFenceDraw)
293 {
294     constexpr int kNumIterations = 10;
295     constexpr int kNumDraws      = 5;
296 
297     // Create a texture/FBO to draw to
298     GLTexture texture;
299     glBindTexture(GL_TEXTURE_2D, texture);
300     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
301     ASSERT_GL_NO_ERROR();
302     GLFramebuffer fbo;
303     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
304     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
305     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
306 
307     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
308     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
309 
310     bool drawGreen = true;
311     for (int numIterations = 0; numIterations < kNumIterations; ++numIterations)
312     {
313         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
314         ASSERT_GL_NO_ERROR();
315 
316         for (int i = 0; i < kNumDraws; ++i)
317         {
318             GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
319             ASSERT_GL_NO_ERROR();
320 
321             drawGreen      = !drawGreen;
322             GLuint program = 0;
323             if (drawGreen)
324             {
325                 program = greenProgram;
326             }
327             else
328             {
329                 program = redProgram;
330             }
331             drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
332             ASSERT_GL_NO_ERROR();
333 
334             glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
335             EXPECT_GL_NO_ERROR();
336             glDeleteSync(sync);
337             ASSERT_GL_NO_ERROR();
338         }
339 
340         // Blit to the default FBO
341         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
342         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
343         glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
344         ASSERT_GL_NO_ERROR();
345         swapBuffers();
346 
347         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
348         GLColor color;
349         if (drawGreen)
350         {
351             color = GLColor::green;
352         }
353         else
354         {
355             color = GLColor::red;
356         }
357         EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, color);
358     }
359 }
360 
361 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FenceNVTest);
362 
363 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FenceSyncTest);
364 ANGLE_INSTANTIATE_TEST_ES3(FenceSyncTest);
365