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     for (size_t i = 0; i < 20; i++)
269     {
270         glClear(GL_COLOR_BUFFER_BIT);
271         glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
272         EXPECT_GL_NO_ERROR();
273     }
274 }
275 
276 // Test that multiple fences and draws can be issued
TEST_P(FenceSyncTest,MultipleFenceDraw)277 TEST_P(FenceSyncTest, MultipleFenceDraw)
278 {
279     constexpr int kNumIterations = 10;
280     constexpr int kNumDraws      = 5;
281 
282     // Create a texture/FBO to draw to
283     GLTexture texture;
284     glBindTexture(GL_TEXTURE_2D, texture.get());
285     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
286     ASSERT_GL_NO_ERROR();
287     GLFramebuffer fbo;
288     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
289     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
290     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
291 
292     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
293     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
294 
295     bool drawGreen = true;
296     for (int numIterations = 0; numIterations < kNumIterations; ++numIterations)
297     {
298         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
299         ASSERT_GL_NO_ERROR();
300 
301         for (int i = 0; i < kNumDraws; ++i)
302         {
303             GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
304             ASSERT_GL_NO_ERROR();
305 
306             drawGreen      = !drawGreen;
307             GLuint program = 0;
308             if (drawGreen)
309             {
310                 program = greenProgram.get();
311             }
312             else
313             {
314                 program = redProgram.get();
315             }
316             drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
317             ASSERT_GL_NO_ERROR();
318 
319             glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
320             EXPECT_GL_NO_ERROR();
321             glDeleteSync(sync);
322             ASSERT_GL_NO_ERROR();
323         }
324 
325         // Blit to the default FBO
326         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
327         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
328         glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
329         ASSERT_GL_NO_ERROR();
330         swapBuffers();
331 
332         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
333         GLColor color;
334         if (drawGreen)
335         {
336             color = GLColor::green;
337         }
338         else
339         {
340             color = GLColor::red;
341         }
342         EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, color);
343     }
344 }
345 
346 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FenceNVTest);
347 
348 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FenceSyncTest);
349 ANGLE_INSTANTIATE_TEST_ES3(FenceSyncTest);
350