// // Copyright 2015 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "test_utils/ANGLETest.h" using namespace angle; class FenceNVTest : public ANGLETest { protected: FenceNVTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); setConfigDepthBits(24); } }; class FenceSyncTest : public ANGLETest { protected: FenceSyncTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); setConfigDepthBits(24); } }; // FenceNV objects should respond false to glIsFenceNV until they've been set TEST_P(FenceNVTest, IsFence) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence")); GLuint fence = 0; glGenFencesNV(1, &fence); EXPECT_GL_NO_ERROR(); EXPECT_GL_FALSE(glIsFenceNV(fence)); EXPECT_GL_NO_ERROR(); glSetFenceNV(fence, GL_ALL_COMPLETED_NV); EXPECT_GL_NO_ERROR(); EXPECT_GL_TRUE(glIsFenceNV(fence)); EXPECT_GL_NO_ERROR(); } // Test error cases for all FenceNV functions TEST_P(FenceNVTest, Errors) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence")); EXPECT_GL_TRUE(glTestFenceNV(10)) << "glTestFenceNV should still return TRUE for an invalid " "fence and generate an INVALID_OPERATION"; EXPECT_GL_ERROR(GL_INVALID_OPERATION); GLuint fence = 20; // glGenFencesNV should generate INVALID_VALUE for a negative n and not write anything to the // fences pointer glGenFencesNV(-1, &fence); EXPECT_GL_ERROR(GL_INVALID_VALUE); EXPECT_EQ(20u, fence); // Generate a real fence glGenFencesNV(1, &fence); EXPECT_GL_NO_ERROR(); EXPECT_GL_TRUE(glTestFenceNV(fence)) << "glTestFenceNV should still return TRUE for a fence " "that is not started and generate an INVALID_OPERATION"; EXPECT_GL_ERROR(GL_INVALID_OPERATION); // glGetFenceivNV should generate an INVALID_OPERATION for an invalid or unstarted fence and not // modify the params GLint result = 30; glGetFenceivNV(10, GL_FENCE_STATUS_NV, &result); EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_EQ(30, result); glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &result); EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_EQ(30, result); // glSetFenceNV should generate an error for any condition that is not ALL_COMPLETED_NV glSetFenceNV(fence, 0); EXPECT_GL_ERROR(GL_INVALID_ENUM); // glSetFenceNV should generate INVALID_OPERATION for an invalid fence glSetFenceNV(10, GL_ALL_COMPLETED_NV); EXPECT_GL_ERROR(GL_INVALID_OPERATION); } // Test that basic usage works and doesn't generate errors or crash TEST_P(FenceNVTest, BasicOperations) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_fence")); glClearColor(1.0f, 0.0f, 1.0f, 1.0f); constexpr size_t kFenceCount = 20; GLuint fences[kFenceCount] = {0}; glGenFencesNV(static_cast(ArraySize(fences)), fences); EXPECT_GL_NO_ERROR(); for (GLuint fence : fences) { glClear(GL_COLOR_BUFFER_BIT); glSetFenceNV(fence, GL_ALL_COMPLETED_NV); } // Finish the last fence, all fences before should be marked complete glFinishFenceNV(fences[kFenceCount - 1]); for (GLuint fence : fences) { GLint status = 0; glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &status); EXPECT_GL_NO_ERROR(); // Fence should be complete now that Finish has been called EXPECT_GL_TRUE(status); } EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255); } // Sync objects should respond true to IsSync after they are created with glFenceSync TEST_P(FenceSyncTest, IsSync) { GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); EXPECT_GL_NO_ERROR(); EXPECT_GL_TRUE(glIsSync(sync)); EXPECT_GL_FALSE(glIsSync(reinterpret_cast(40))); } // Test error cases for all Sync function TEST_P(FenceSyncTest, Errors) { GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); // DeleteSync generates INVALID_VALUE when the sync is not valid glDeleteSync(reinterpret_cast(20)); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glFenceSync generates GL_INVALID_ENUM if the condition is not GL_SYNC_GPU_COMMANDS_COMPLETE EXPECT_EQ(0, glFenceSync(0, 0)); EXPECT_GL_ERROR(GL_INVALID_ENUM); // glFenceSync generates GL_INVALID_ENUM if the flags is not 0 EXPECT_EQ(0, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 10)); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if flags contains more // than just GL_SYNC_FLUSH_COMMANDS_BIT EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT | 0x2, 0)); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if the sync object is // not valid EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(reinterpret_cast(30), GL_SYNC_FLUSH_COMMANDS_BIT, 0)); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glWaitSync generates GL_INVALID_VALUE if flags is non-zero glWaitSync(sync, 1, GL_TIMEOUT_IGNORED); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glWaitSync generates GL_INVALID_VALUE if GLuint64 is not GL_TIMEOUT_IGNORED glWaitSync(sync, 0, 0); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glWaitSync generates GL_INVALID_VALUE if the sync object is not valid glWaitSync(reinterpret_cast(30), 0, GL_TIMEOUT_IGNORED); EXPECT_GL_ERROR(GL_INVALID_VALUE); // glGetSynciv generates GL_INVALID_VALUE if bufSize is less than zero, results should be // untouched GLsizei length = 20; GLint value = 30; glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &value); EXPECT_GL_ERROR(GL_INVALID_VALUE); EXPECT_EQ(20, length); EXPECT_EQ(30, value); // glGetSynciv generates GL_INVALID_VALUE if the sync object is not valid, results should be // untouched glGetSynciv(reinterpret_cast(30), GL_OBJECT_TYPE, 1, &length, &value); EXPECT_GL_ERROR(GL_INVALID_VALUE); EXPECT_EQ(20, length); EXPECT_EQ(30, value); } // Test usage of glGetSynciv TEST_P(FenceSyncTest, BasicQueries) { GLsizei length = 0; GLint value = 0; GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glGetSynciv(sync, GL_SYNC_CONDITION, 1, &length, &value); EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_SYNC_GPU_COMMANDS_COMPLETE, value); glGetSynciv(sync, GL_OBJECT_TYPE, 1, &length, &value); EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_SYNC_FENCE, value); glGetSynciv(sync, GL_SYNC_FLAGS, 1, &length, &value); EXPECT_GL_NO_ERROR(); EXPECT_EQ(0, value); } // Test that basic usage works and doesn't generate errors or crash TEST_P(FenceSyncTest, BasicOperations) { glClearColor(1.0f, 0.0f, 1.0f, 1.0f); GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glClear(GL_COLOR_BUFFER_BIT); glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); EXPECT_GL_NO_ERROR(); GLsizei length = 0; GLint value = 0; unsigned int loopCount = 0; glFlush(); // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop while (value != GL_SIGNALED && loopCount <= 1000000) { loopCount++; glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value); ASSERT_GL_NO_ERROR(); } ASSERT_GLENUM_EQ(GL_SIGNALED, value); for (size_t i = 0; i < 20; i++) { glClear(GL_COLOR_BUFFER_BIT); glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); EXPECT_GL_NO_ERROR(); } } // Use this to select which configurations (e.g. which renderer, which GLES major version) these // tests should be run against. ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FenceNVTest); ANGLE_INSTANTIATE_TEST_ES3(FenceSyncTest);