• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = 1024;
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 that basic usage works and doesn't generate errors or crash
TEST_P(FenceSyncTest,BasicOperations)231 TEST_P(FenceSyncTest, BasicOperations)
232 {
233     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
234 
235     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
236 
237     glClear(GL_COLOR_BUFFER_BIT);
238     glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
239     EXPECT_GL_NO_ERROR();
240 
241     GLsizei length         = 0;
242     GLint value            = 0;
243     unsigned int loopCount = 0;
244 
245     glFlush();
246 
247     // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
248     while (value != GL_SIGNALED && loopCount <= 1000000)
249     {
250         loopCount++;
251 
252         glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value);
253         ASSERT_GL_NO_ERROR();
254     }
255 
256     ASSERT_GLENUM_EQ(GL_SIGNALED, value);
257 
258     for (size_t i = 0; i < 20; i++)
259     {
260         glClear(GL_COLOR_BUFFER_BIT);
261         glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
262         EXPECT_GL_NO_ERROR();
263     }
264 }
265 
266 // Test that multiple fences and draws can be issued
TEST_P(FenceSyncTest,MultipleFenceDraw)267 TEST_P(FenceSyncTest, MultipleFenceDraw)
268 {
269     constexpr int kNumIterations = 10;
270     constexpr int kNumDraws      = 5;
271 
272     // Create a texture/FBO to draw to
273     GLTexture texture;
274     glBindTexture(GL_TEXTURE_2D, texture.get());
275     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
276     ASSERT_GL_NO_ERROR();
277     GLFramebuffer fbo;
278     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
279     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
280     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
281 
282     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
283     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
284 
285     bool drawGreen = true;
286     for (int numIterations = 0; numIterations < kNumIterations; ++numIterations)
287     {
288         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
289         ASSERT_GL_NO_ERROR();
290 
291         for (int i = 0; i < kNumDraws; ++i)
292         {
293             GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
294             ASSERT_GL_NO_ERROR();
295 
296             drawGreen      = !drawGreen;
297             GLuint program = 0;
298             if (drawGreen)
299             {
300                 program = greenProgram.get();
301             }
302             else
303             {
304                 program = redProgram.get();
305             }
306             drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
307             ASSERT_GL_NO_ERROR();
308 
309             glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
310             EXPECT_GL_NO_ERROR();
311             glDeleteSync(sync);
312             ASSERT_GL_NO_ERROR();
313         }
314 
315         // Blit to the default FBO
316         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
317         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
318         glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
319         ASSERT_GL_NO_ERROR();
320         swapBuffers();
321 
322         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
323         GLColor color;
324         if (drawGreen)
325         {
326             color = GLColor::green;
327         }
328         else
329         {
330             color = GLColor::red;
331         }
332         EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, color);
333     }
334 }
335 
336 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FenceNVTest);
337 
338 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FenceSyncTest);
339 ANGLE_INSTANTIATE_TEST_ES3(FenceSyncTest);
340