// // 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) { if (!extensionEnabled("GL_NV_fence")) { std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl; return; } GLuint fence = 0; glGenFencesNV(1, &fence); EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_FALSE, glIsFenceNV(fence)); EXPECT_GL_NO_ERROR(); glSetFenceNV(fence, GL_ALL_COMPLETED_NV); EXPECT_GL_NO_ERROR(); EXPECT_EQ(GL_TRUE, glIsFenceNV(fence)); EXPECT_GL_NO_ERROR(); } // Test error cases for all FenceNV functions TEST_P(FenceNVTest, Errors) { if (!extensionEnabled("GL_NV_fence")) { std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl; return; } // glTestFenceNV should still return TRUE for an invalid fence and generate an INVALID_OPERATION EXPECT_EQ(GL_TRUE, glTestFenceNV(10)); 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(); // glTestFenceNV should still return TRUE for a fence that is not started and generate an INVALID_OPERATION EXPECT_EQ(GL_TRUE, glTestFenceNV(fence)); 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) { if (!extensionEnabled("GL_NV_fence")) { std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl; return; } glClearColor(1.0f, 0.0f, 1.0f, 1.0f); GLuint fences[20] = { 0 }; glGenFencesNV(static_cast(ArraySize(fences)), fences); EXPECT_GL_NO_ERROR(); for (GLuint fence : fences) { glSetFenceNV(fence, GL_ALL_COMPLETED_NV); glClear(GL_COLOR_BUFFER_BIT); } glFinish(); 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_EQ(GL_TRUE, status); } EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255); } // FenceSync 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_EQ(GL_TRUE, glIsSync(sync)); EXPECT_EQ(GL_FALSE, glIsSync(reinterpret_cast(40))); } // Test error cases for all FenceSync 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 tis 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) { // TODO(geofflang): Figure out why this is broken on Intel OpenGL if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) { std::cout << "Test skipped on Intel OpenGL." << std::endl; return; } 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(FenceNVTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL(), ES2_OPENGLES(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(FenceSyncTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());