1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Sync tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3fSyncTests.hpp" 25 26#include "tcuTestLog.hpp" 27#include "tcuVector.hpp" 28#include "gluShaderProgram.hpp" 29#include "gluCallLogWrapper.hpp" 30#include "gluRenderContext.hpp" 31#include "glwEnums.hpp" 32#include "deRandom.hpp" 33#include "deStringUtil.hpp" 34#include "deString.h" 35 36#include <vector> 37 38using tcu::TestLog; 39 40namespace deqp 41{ 42namespace gles3 43{ 44namespace Functional 45{ 46 47using namespace glw; // GL types 48 49static const int NUM_CASE_ITERATIONS = 5; 50 51enum WaitCommand 52{ 53 COMMAND_WAIT_SYNC = 1 << 0, 54 COMMAND_CLIENT_WAIT_SYNC = 1 << 1 55}; 56 57enum CaseOptions 58{ 59 CASE_FLUSH_BEFORE_WAIT = 1 << 0, 60 CASE_FINISH_BEFORE_WAIT = 1 << 1 61}; 62 63class FenceSyncCase : public TestCase, private glu::CallLogWrapper 64{ 65public: 66 FenceSyncCase (Context& context, const char* name, const char* description, int numPrimitives, deUint32 waitCommand, deUint32 waitFlags, deUint64 timeout, deUint32 options); 67 ~FenceSyncCase (void); 68 69 void init (void); 70 void deinit (void); 71 IterateResult iterate (void); 72 73private: 74 FenceSyncCase (const FenceSyncCase& other); 75 FenceSyncCase& operator= (const FenceSyncCase& other); 76 77 int m_numPrimitives; 78 deUint32 m_waitCommand; 79 deUint32 m_waitFlags; 80 deUint64 m_timeout; 81 deUint32 m_caseOptions; 82 83 glu::ShaderProgram* m_program; 84 GLsync m_syncObject; 85 int m_iterNdx; 86 de::Random m_rnd; 87}; 88 89FenceSyncCase::FenceSyncCase (Context& context, const char* name, const char* description, int numPrimitives, deUint32 waitCommand, deUint32 waitFlags, deUint64 timeout, deUint32 options) 90 : TestCase (context, name, description) 91 , CallLogWrapper (context.getRenderContext().getFunctions(), context.getTestContext().getLog()) 92 , m_numPrimitives (numPrimitives) 93 , m_waitCommand (waitCommand) 94 , m_waitFlags (waitFlags) 95 , m_timeout (timeout) 96 , m_caseOptions (options) 97 , m_program (DE_NULL) 98 , m_syncObject (DE_NULL) 99 , m_iterNdx (0) 100 , m_rnd (deStringHash(name)) 101{ 102} 103 104FenceSyncCase::~FenceSyncCase (void) 105{ 106 FenceSyncCase::deinit(); 107} 108 109static void generateVertices (std::vector<float>& dst, int numPrimitives, de::Random& rnd) 110{ 111 int numVertices = 3*numPrimitives; 112 dst.resize(numVertices * 4); 113 114 for (int i = 0; i < numVertices; i++) 115 { 116 dst[i*4 ] = rnd.getFloat(-1.0f, 1.0f); // x 117 dst[i*4 + 1] = rnd.getFloat(-1.0f, 1.0f); // y 118 dst[i*4 + 2] = rnd.getFloat( 0.0f, 1.0f); // z 119 dst[i*4 + 3] = 1.0f; // w 120 } 121} 122 123void FenceSyncCase::init (void) 124{ 125 const char* vertShaderSource = 126 "#version 300 es\n" 127 "layout(location = 0) in mediump vec4 a_position;\n" 128 "\n" 129 "void main (void)\n" 130 "{\n" 131 " gl_Position = a_position;\n" 132 "}\n"; 133 134 const char* fragShaderSource = 135 "#version 300 es\n" 136 "layout(location = 0) out mediump vec4 o_color;\n" 137 "\n" 138 "void main (void)\n" 139 "{\n" 140 " o_color = vec4(0.25, 0.5, 0.75, 1.0);\n" 141 "}\n"; 142 143 DE_ASSERT(!m_program); 144 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource)); 145 146 if (!m_program->isOk()) 147 { 148 m_testCtx.getLog() << *m_program; 149 TCU_FAIL("Failed to compile shader program"); 150 } 151 152 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass. 153 GLU_CHECK_MSG("Case initialization finished"); 154} 155 156void FenceSyncCase::deinit (void) 157{ 158 if (m_program) 159 { 160 delete m_program; 161 m_program = DE_NULL; 162 } 163 164 if (m_syncObject) 165 { 166 glDeleteSync(m_syncObject); 167 m_syncObject = DE_NULL; 168 } 169} 170 171FenceSyncCase::IterateResult FenceSyncCase::iterate (void) 172{ 173 TestLog& log = m_testCtx.getLog(); 174 std::vector<float> vertices; 175 bool testOk = true; 176 177 std::string header = "Case iteration " + de::toString(m_iterNdx+1) + " / " + de::toString(NUM_CASE_ITERATIONS); 178 const tcu::ScopedLogSection section (log, header, header); 179 180 enableLogging(true); 181 182 DE_ASSERT (m_program); 183 glUseProgram (m_program->getProgram()); 184 glEnable (GL_DEPTH_TEST); 185 glClearColor (0.3f, 0.3f, 0.3f, 1.0f); 186 glClearDepthf (1.0f); 187 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 188 189 // Generate vertices 190 191 glEnableVertexAttribArray (0); 192 generateVertices (vertices, m_numPrimitives, m_rnd); 193 glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]); 194 195 // Draw 196 197 glDrawArrays(GL_TRIANGLES, 0, (int)vertices.size() / 4); 198 log << TestLog::Message << "// Primitives drawn." << TestLog::EndMessage; 199 200 // Create sync object 201 202 m_syncObject = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 203 GLU_CHECK_MSG ("Sync object created"); 204 log << TestLog::Message << "// Sync object created." << TestLog::EndMessage; 205 206 if (m_caseOptions & CASE_FLUSH_BEFORE_WAIT) 207 glFlush(); 208 if (m_caseOptions & CASE_FINISH_BEFORE_WAIT) 209 glFinish(); 210 211 // Wait for sync object 212 213 GLenum waitValue = 0; 214 215 if (m_waitCommand & COMMAND_WAIT_SYNC) 216 { 217 DE_ASSERT(m_timeout == GL_TIMEOUT_IGNORED); 218 DE_ASSERT(m_waitFlags == 0); 219 glWaitSync(m_syncObject, m_waitFlags, m_timeout); 220 GLU_CHECK_MSG ("glWaitSync called"); 221 log << TestLog::Message << "// Wait command glWaitSync called with GL_TIMEOUT_IGNORED." << TestLog::EndMessage; 222 } 223 if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC) 224 { 225 waitValue = glClientWaitSync(m_syncObject, m_waitFlags, m_timeout); 226 GLU_CHECK_MSG ("glClientWaitSync called"); 227 log << TestLog::Message << "// glClientWaitSync return value:" << TestLog::EndMessage; 228 switch (waitValue) 229 { 230 case GL_ALREADY_SIGNALED: log << TestLog::Message << "// GL_ALREADY_SIGNALED" << TestLog::EndMessage; break; 231 case GL_TIMEOUT_EXPIRED: log << TestLog::Message << "// GL_TIMEOUT_EXPIRED" << TestLog::EndMessage; break; 232 case GL_CONDITION_SATISFIED: log << TestLog::Message << "// GL_CONDITION_SATISFIED" << TestLog::EndMessage; break; 233 case GL_WAIT_FAILED: log << TestLog::Message << "// GL_WAIT_FAILED" << TestLog::EndMessage; testOk = false; break; 234 default: TCU_FAIL("// Illegal return value!"); 235 } 236 } 237 238 glFinish(); 239 240 if (m_caseOptions & CASE_FINISH_BEFORE_WAIT && waitValue != GL_ALREADY_SIGNALED) 241 { 242 testOk = false; 243 log << TestLog::Message << "// Expected glClientWaitSync to return GL_ALREADY_SIGNALED." << TestLog::EndMessage; 244 } 245 246 // Delete sync object 247 248 if (m_syncObject) 249 { 250 glDeleteSync(m_syncObject); 251 m_syncObject = DE_NULL; 252 GLU_CHECK_MSG ("Sync object deleted"); 253 log << TestLog::Message << "// Sync object deleted." << TestLog::EndMessage; 254 } 255 256 // Evaluate test result 257 258 log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage; 259 260 if (!testOk) 261 { 262 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 263 return STOP; 264 } 265 266 log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage; 267 268 return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP; 269} 270 271SyncTests::SyncTests (Context& context) 272 : TestCaseGroup(context, "fence_sync", "Fence Sync Tests") 273{ 274} 275 276SyncTests::~SyncTests (void) 277{ 278} 279 280void SyncTests::init (void) 281{ 282 // Fence sync tests. 283 284 addChild(new FenceSyncCase(m_context, "wait_sync_smalldraw", "", 10, COMMAND_WAIT_SYNC, 0, GL_TIMEOUT_IGNORED, 0)); 285 addChild(new FenceSyncCase(m_context, "wait_sync_largedraw", "", 10000, COMMAND_WAIT_SYNC, 0, GL_TIMEOUT_IGNORED, 0)); 286 287 addChild(new FenceSyncCase(m_context, "client_wait_sync_smalldraw", "", 10, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0)); 288 addChild(new FenceSyncCase(m_context, "client_wait_sync_largedraw", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0)); 289 addChild(new FenceSyncCase(m_context, "client_wait_sync_timeout_smalldraw", "", 10, COMMAND_CLIENT_WAIT_SYNC, 0, 10, 0)); 290 addChild(new FenceSyncCase(m_context, "client_wait_sync_timeout_largedraw", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 10, 0)); 291 292 addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_auto", "", 10000, COMMAND_CLIENT_WAIT_SYNC, GL_SYNC_FLUSH_COMMANDS_BIT, 0, 0)); 293 addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_manual", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, CASE_FLUSH_BEFORE_WAIT)); 294 addChild(new FenceSyncCase(m_context, "client_wait_sync_noflush", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0)); 295 addChild(new FenceSyncCase(m_context, "client_wait_sync_finish", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, CASE_FINISH_BEFORE_WAIT)); 296} 297 298} // Functional 299} // gles3 300} // deqp 301