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 
9 using namespace angle;
10 
11 class FenceNVTest : public ANGLETest
12 {
13   protected:
FenceNVTest()14     FenceNVTest()
15     {
16         setWindowWidth(128);
17         setWindowHeight(128);
18         setConfigRedBits(8);
19         setConfigGreenBits(8);
20         setConfigBlueBits(8);
21         setConfigAlphaBits(8);
22         setConfigDepthBits(24);
23     }
24 };
25 
26 class FenceSyncTest : public ANGLETest
27 {
28   protected:
FenceSyncTest()29     FenceSyncTest()
30     {
31         setWindowWidth(128);
32         setWindowHeight(128);
33         setConfigRedBits(8);
34         setConfigGreenBits(8);
35         setConfigBlueBits(8);
36         setConfigAlphaBits(8);
37         setConfigDepthBits(24);
38     }
39 };
40 
41 // FenceNV objects should respond false to glIsFenceNV until they've been set
TEST_P(FenceNVTest,IsFence)42 TEST_P(FenceNVTest, IsFence)
43 {
44     if (!extensionEnabled("GL_NV_fence"))
45     {
46         std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
47         return;
48     }
49 
50     GLuint fence = 0;
51     glGenFencesNV(1, &fence);
52     EXPECT_GL_NO_ERROR();
53 
54     EXPECT_EQ(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_EQ(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     if (!extensionEnabled("GL_NV_fence"))
68     {
69         std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
70         return;
71     }
72 
73     // glTestFenceNV should still return TRUE for an invalid fence and generate an INVALID_OPERATION
74     EXPECT_EQ(GL_TRUE, glTestFenceNV(10));
75     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
76 
77     GLuint fence = 20;
78 
79     // glGenFencesNV should generate INVALID_VALUE for a negative n and not write anything to the fences pointer
80     glGenFencesNV(-1, &fence);
81     EXPECT_GL_ERROR(GL_INVALID_VALUE);
82     EXPECT_EQ(20u, fence);
83 
84     // Generate a real fence
85     glGenFencesNV(1, &fence);
86     EXPECT_GL_NO_ERROR();
87 
88     // glTestFenceNV should still return TRUE for a fence that is not started and generate an INVALID_OPERATION
89     EXPECT_EQ(GL_TRUE, glTestFenceNV(fence));
90     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
91 
92     // glGetFenceivNV should generate an INVALID_OPERATION for an invalid or unstarted fence and not modify the params
93     GLint result = 30;
94     glGetFenceivNV(10, GL_FENCE_STATUS_NV, &result);
95     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
96     EXPECT_EQ(30, result);
97 
98     glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &result);
99     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
100     EXPECT_EQ(30, result);
101 
102     // glSetFenceNV should generate an error for any condition that is not ALL_COMPLETED_NV
103     glSetFenceNV(fence, 0);
104     EXPECT_GL_ERROR(GL_INVALID_ENUM);
105 
106     // glSetFenceNV should generate INVALID_OPERATION for an invalid fence
107     glSetFenceNV(10, GL_ALL_COMPLETED_NV);
108     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
109 }
110 
111 // Test that basic usage works and doesn't generate errors or crash
TEST_P(FenceNVTest,BasicOperations)112 TEST_P(FenceNVTest, BasicOperations)
113 {
114     if (!extensionEnabled("GL_NV_fence"))
115     {
116         std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
117         return;
118     }
119 
120     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
121 
122     GLuint fences[20] = { 0 };
123     glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences);
124     EXPECT_GL_NO_ERROR();
125 
126     for (GLuint fence : fences)
127     {
128         glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
129 
130         glClear(GL_COLOR_BUFFER_BIT);
131     }
132 
133     glFinish();
134 
135     for (GLuint fence : fences)
136     {
137         GLint status = 0;
138         glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &status);
139         EXPECT_GL_NO_ERROR();
140 
141         // Fence should be complete now that Finish has been called
142         EXPECT_EQ(GL_TRUE, status);
143     }
144 
145     EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255);
146 }
147 
148 // FenceSync objects should respond true to IsSync after they are created with glFenceSync
TEST_P(FenceSyncTest,IsSync)149 TEST_P(FenceSyncTest, IsSync)
150 {
151     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
152     EXPECT_GL_NO_ERROR();
153 
154     EXPECT_EQ(GL_TRUE, glIsSync(sync));
155     EXPECT_EQ(GL_FALSE, glIsSync(reinterpret_cast<GLsync>(40)));
156 }
157 
158 // Test error cases for all FenceSync function
TEST_P(FenceSyncTest,Errors)159 TEST_P(FenceSyncTest, Errors)
160 {
161     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
162 
163     // DeleteSync generates INVALID_VALUE when the sync is not valid
164     glDeleteSync(reinterpret_cast<GLsync>(20));
165     EXPECT_GL_ERROR(GL_INVALID_VALUE);
166 
167     // glFenceSync generates GL_INVALID_ENUM if the condition is not GL_SYNC_GPU_COMMANDS_COMPLETE
168     EXPECT_EQ(0, glFenceSync(0, 0));
169     EXPECT_GL_ERROR(GL_INVALID_ENUM);
170 
171     // glFenceSync generates GL_INVALID_ENUM if the flags is not 0
172     EXPECT_EQ(0, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 10));
173     EXPECT_GL_ERROR(GL_INVALID_VALUE);
174 
175     // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if flags contains more than just GL_SYNC_FLUSH_COMMANDS_BIT
176     EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT | 0x2, 0));
177     EXPECT_GL_ERROR(GL_INVALID_VALUE);
178 
179     // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if the sync object is not valid
180     EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(reinterpret_cast<GLsync>(30), GL_SYNC_FLUSH_COMMANDS_BIT, 0));
181     EXPECT_GL_ERROR(GL_INVALID_VALUE);
182 
183     // glWaitSync generates GL_INVALID_VALUE if flags is non-zero
184     glWaitSync(sync, 1, GL_TIMEOUT_IGNORED);
185     EXPECT_GL_ERROR(GL_INVALID_VALUE);
186 
187     // glWaitSync generates GL_INVALID_VALUE if GLuint64 is not GL_TIMEOUT_IGNORED
188     glWaitSync(sync, 0, 0);
189     EXPECT_GL_ERROR(GL_INVALID_VALUE);
190 
191     // glWaitSync generates GL_INVALID_VALUE if the sync object is not valid
192     glWaitSync(reinterpret_cast<GLsync>(30), 0, GL_TIMEOUT_IGNORED);
193     EXPECT_GL_ERROR(GL_INVALID_VALUE);
194 
195     // glGetSynciv generates GL_INVALID_VALUE if bufSize is less than zero, results should be untouched
196     GLsizei length = 20;
197     GLint value = 30;
198     glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &value);
199     EXPECT_GL_ERROR(GL_INVALID_VALUE);
200     EXPECT_EQ(20, length);
201     EXPECT_EQ(30, value);
202 
203     // glGetSynciv generates GL_INVALID_VALUE if the sync object tis not valid, results should be 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     // TODO(geofflang): Figure out why this is broken on Intel OpenGL
234     if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
235     {
236         std::cout << "Test skipped on Intel OpenGL." << std::endl;
237         return;
238     }
239 
240     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
241 
242     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
243 
244     glClear(GL_COLOR_BUFFER_BIT);
245     glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
246     EXPECT_GL_NO_ERROR();
247 
248     GLsizei length = 0;
249     GLint value = 0;
250     unsigned int loopCount = 0;
251 
252     glFlush();
253 
254     // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
255     while (value != GL_SIGNALED && loopCount <= 1000000)
256     {
257         loopCount++;
258 
259         glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value);
260         ASSERT_GL_NO_ERROR();
261     }
262 
263     ASSERT_GLENUM_EQ(GL_SIGNALED, value);
264 
265     for (size_t i = 0; i < 20; i++)
266     {
267         glClear(GL_COLOR_BUFFER_BIT);
268         glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
269         EXPECT_GL_NO_ERROR();
270     }
271 }
272 
273 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
274 ANGLE_INSTANTIATE_TEST(FenceNVTest,
275                        ES2_D3D9(),
276                        ES2_D3D11(),
277                        ES3_D3D11(),
278                        ES2_OPENGL(),
279                        ES3_OPENGL(),
280                        ES2_OPENGLES(),
281                        ES3_OPENGLES());
282 ANGLE_INSTANTIATE_TEST(FenceSyncTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
283