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