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