enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; BOOL fence_result; TRACE("(%p) : device %p\n", query, device); if (query->context == NULL) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId()) { #ifdef VBOX_WINE_WITH_SINGLE_CONTEXT ERR("Event query tested from wrong thread\n"); #else WARN("Event query tested from wrong thread\n"); #endif return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; ENTER_GL(); if (gl_info->supported[ARB_SYNC]) { GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; case GL_TIMEOUT_EXPIRED: ret = WINED3D_EVENT_QUERY_WAITING; break; case GL_WAIT_FAILED: default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (gl_info->supported[APPLE_FENCE]) { fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id)); checkGLcall("glTestFenceAPPLE"); if (fence_result) ret = WINED3D_EVENT_QUERY_OK; else ret = WINED3D_EVENT_QUERY_WAITING; } else if (gl_info->supported[NV_FENCE]) { fence_result = GL_EXTCALL(glTestFenceNV(query->object.id)); checkGLcall("glTestFenceNV"); if (fence_result) ret = WINED3D_EVENT_QUERY_OK; else ret = WINED3D_EVENT_QUERY_WAITING; } else { ERR("Event query created despite lack of GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } LEAVE_GL(); context_release(context); return ret; }
enum piglit_result piglit_display(void) { float white[4] = {1.0, 1.0, 1.0, 1.0}; GLboolean pass = GL_TRUE; int i; #ifdef PIGLIT_USE_OPENGL float array[] = { 17, 13, 0, 17, 18, 0, 12, 13, 0, 12, 18, 0, 27, 13, 0, 27, 18, 0, 22, 13, 0, 22, 18, 0, 37, 13, 0, 37, 18, 0, 32, 13, 0, 32, 18, 0, 47, 13, 0, 47, 18, 0, 42, 13, 0, 42, 18, 0 }; #else // PIGLIT_USE_OPENGL_ES3 float array[] = { 1.00, 0.75, 0.0, 1.00, 1.00, 0.0, 0.75, 0.75, 0.0, 0.75, 1.00, 0.0, 0.50, 0.75, 0.0, 0.50, 1.00, 0.0, 0.25, 0.75, 0.0, 0.25, 1.00, 0.0, 0.00, 0.75, 0.0, 0.00, 1.00, 0.0, -0.25, 0.75, 0.0, -0.25, 1.00, 0.0, -0.50, 0.75, 0.0, -0.50, 1.00, 0.0, -0.75, 0.75, 0.0, -0.75, 1.00, 0.0, }; #endif glClear(GL_COLOR_BUFFER_BIT); if (test == DRAW) { #ifdef PIGLIT_USE_OPENGL glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, buffer); glVertexPointer(3, GL_FLOAT, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); #else // PIGLIT_USE_OPENGL_ES3 glBindVertexArray(vao); #endif memcpy(map, array, 12 * sizeof(float)); if (!coherent) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); memcpy(map+12, array+12, 12 * sizeof(float)); if (!coherent) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 4, 4); memcpy(map+12*2, array+12*2, 12 * sizeof(float)); if (!coherent) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 8, 4); memcpy(map+12*3, array+12*3, 12 * sizeof(float)); if (!coherent) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 12, 4); piglit_check_gl_error(0); #ifdef PIGLIT_USE_OPENGL pass = pass && piglit_probe_pixel_rgb(15, 15, white); pass = pass && piglit_probe_pixel_rgb(25, 15, white); pass = pass && piglit_probe_pixel_rgb(35, 15, white); pass = pass && piglit_probe_pixel_rgb(45, 15, white); glDisableClientState(GL_VERTEX_ARRAY); #else // PIGLIT_USE_OPENGL_ES3 pass = pass && piglit_probe_pixel_rgba(13, 87, white); pass = pass && piglit_probe_pixel_rgba(39, 87, white); pass = pass && piglit_probe_pixel_rgba(65, 87, white); pass = pass && piglit_probe_pixel_rgba(91, 87, white); #endif } else if (test == READ) { GLuint srcbuf; GLsync fence; glGenBuffers(1, &srcbuf); glBindBuffer(GL_COPY_READ_BUFFER, srcbuf); glBufferData(GL_COPY_READ_BUFFER, BUF_SIZE, array, GL_STATIC_DRAW); /* Copy some data to the mapped buffer and check if the CPU can see it. */ glBindBuffer(GL_COPY_WRITE_BUFFER, buffer); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, BUF_SIZE); glBindBuffer(GL_COPY_READ_BUFFER, 0); glBindBuffer(GL_COPY_WRITE_BUFFER, 0); glDeleteBuffers(1, &srcbuf); if (!coherent) glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); for (i = 0; i < ARRAY_SIZE(array); i++) { if (map[i] != array[i]) { printf("Probe [%i] failed. Expected: %f Observed: %f\n", i, array[i], map[i]); pass = GL_FALSE; } } } else { assert(0); } piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; TRACE("(%p)\n", query); if (!query->context) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } gl_info = query->context->gl_info; if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC]) { /* A glFinish does not reliably wait for draws in other contexts. The caller has * to find its own way to cope with the thread switch */ #ifdef VBOX_WINE_WITH_SINGLE_CONTEXT ERR("Event query finished from wrong thread\n"); #else WARN("Event query finished from wrong thread\n"); #endif return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); ENTER_GL(); if (gl_info->supported[ARB_SYNC]) { GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, ~(GLuint64)0)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; /* We don't expect a timeout for a ~584 year wait */ default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (context->gl_info->supported[APPLE_FENCE]) { GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); checkGLcall("glFinishFenceAPPLE"); ret = WINED3D_EVENT_QUERY_OK; } else if (context->gl_info->supported[NV_FENCE]) { GL_EXTCALL(glFinishFenceNV(query->object.id)); checkGLcall("glFinishFenceNV"); ret = WINED3D_EVENT_QUERY_OK; } else { ERR("Event query created without GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } LEAVE_GL(); context_release(context); return ret; }
enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query, const struct wined3d_device *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; TRACE("(%p)\n", query); if (!query->context) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } gl_info = query->context->gl_info; if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC]) { /* A glFinish does not reliably wait for draws in other contexts. The caller has * to find its own way to cope with the thread switch */ WARN("Event query finished from wrong thread\n"); return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, query->context->current_rt); if (gl_info->supported[ARB_SYNC]) { /* Apple seems to be into arbitrary limits, and timeouts larger than * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't * really care and can live with waiting a few μs less. (OS X 10.7.4). */ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; /* We don't expect a timeout for a ~584 year wait */ default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (context->gl_info->supported[APPLE_FENCE]) { GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); checkGLcall("glFinishFenceAPPLE"); ret = WINED3D_EVENT_QUERY_OK; } else if (context->gl_info->supported[NV_FENCE]) { GL_EXTCALL(glFinishFenceNV(query->object.id)); checkGLcall("glFinishFenceNV"); ret = WINED3D_EVENT_QUERY_OK; } else { ERR("Event query created without GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } context_release(context); return ret; }
/** Update shadowSplit values and make Cascade Bounding Box pointer valid. * The function aunches two compute kernel that generates an histogram of the depth buffer value (between 0 and 250 with increment of 0.25) * and get an axis aligned bounding box (from SunCamMatrix view) containing all depth buffer value. * It also retrieves the result from the previous computations (in a Round Robin fashion) and update CBB pointer. * \param width of the depth buffer * \param height of the depth buffer * TODO : The depth histogram part is commented out, needs to tweak it when I have some motivation */ void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height) { // Value that should be kept between multiple calls static GLuint ssbo[2]; static Histogram *Hist[2]; static GLsync LightcoordBBFence = 0; static size_t currentHist = 0; static GLuint ssboSplit[2]; static float tmpshadowSplit[5] = { 1., 5., 20., 50., 150. }; if (!LightcoordBBFence) { glGenBuffers(2, ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); CBB[0] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); CBB[1] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); /* glGenBuffers(2, ssboSplit); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[0]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); Hist[0] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[1]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); Hist[1] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);*/ } // Use bounding boxes from last frame if (LightcoordBBFence) { while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED); glDeleteSync(LightcoordBBFence); } /* { memcpy(shadowSplit, tmpshadowSplit, 5 * sizeof(float)); unsigned numpix = Hist[currentHist]->count; unsigned split = 0; unsigned i; for (i = 0; i < 1022; i++) { split += Hist[currentHist]->bin[i]; if (split > numpix / 2) break; } tmpshadowSplit[1] = (float)++i / 4.; for (; i < 1023; i++) { split += Hist[currentHist]->bin[i]; if (split > 3 * numpix / 4) break; } tmpshadowSplit[2] = (float)++i / 4.; for (; i < 1024; i++) { split += Hist[currentHist]->bin[i]; if (split > 7 * numpix / 8) break; } tmpshadowSplit[3] = (float)++i / 4.; for (; i < 1024; i++) { split += Hist[currentHist]->bin[i]; } tmpshadowSplit[0] = (float)(Hist[currentHist]->bin[1024] - 1) / 4.; tmpshadowSplit[4] = (float)(Hist[currentHist]->bin[1025] + 1) / 4.; printf("numpix is %d\n", numpix); printf("total : %d\n", split); printf("split 0 : %f\n", tmpshadowSplit[1]); printf("split 1 : %f\n", tmpshadowSplit[2]); printf("split 2 : %f\n", tmpshadowSplit[3]); printf("min %f max %f\n", tmpshadowSplit[0], tmpshadowSplit[4]); currentHist = (currentHist + 1) % 2; }*/ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]); // glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboSplit[currentHist]); for (unsigned i = 0; i < 4; i++) { CBB[currentCBB][i].xmin = CBB[currentCBB][i].ymin = CBB[currentCBB][i].zmin = 1000; CBB[currentCBB][i].xmax = CBB[currentCBB][i].ymax = CBB[currentCBB][i].zmax = -1000; } // memset(Hist[currentHist], 0, sizeof(Histogram)); // Hist[currentHist]->mindepth = 3000; glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); glUseProgram(FullScreenShader::LightspaceBoundingBoxShader::getInstance()->Program); FullScreenShader::LightspaceBoundingBoxShader::getInstance()->SetTextureUnits(getDepthStencilTexture()); FullScreenShader::LightspaceBoundingBoxShader::getInstance()->setUniforms(m_suncam->getViewMatrix(), tmpshadowSplit[1], tmpshadowSplit[2], tmpshadowSplit[3], tmpshadowSplit[4]); glDispatchCompute((int)width / 64, (int)height / 64, 1); /* glUseProgram(FullScreenShader::DepthHistogramShader::getInstance()->Program); FullScreenShader::DepthHistogramShader::getInstance()->SetTextureUnits(getDepthStencilTexture()); FullScreenShader::DepthHistogramShader::getInstance()->setUniforms(); glDispatchCompute((int)width / 32, (int)height / 32, 1);*/ glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); LightcoordBBFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); currentCBB = (currentCBB + 1) % 2; }
void base::app::process_captured_screen() { while(_rb_tail != _rb_head) { const int screen_size = get_wnd_width() * get_wnd_height() * base::get_pfd(CAPTURE_PF)->_size; const int tmp_tail = (_rb_tail + 1) & RB_BUFFERS_MASK; screen_buffer *sc = _screen_buffers_rb + tmp_tail; GLenum res = glClientWaitSync(sc->_fence, 0, 0); if(res == GL_ALREADY_SIGNALED || res == GL_CONDITION_SATISFIED) { // AMD returns GL_CONDITION_SATISFIED only BUG? glDeleteSync(sc->_fence); _timer.start(); if(base::cfg().use_pinned_memory) { // process data //memcpy(ptr_dst, sc->_pinned_ptr_aligned, screen_size); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sc->_buffer); } else { glBindBuffer(GL_COPY_READ_BUFFER, sc->_buffer); /*glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sc->_showtime_buffer); char *ptr_dst = reinterpret_cast<char*>( glMapBufferRange( GL_PIXEL_UNPACK_BUFFER, 0, screen_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));*/ char *ptr_src = reinterpret_cast<char*>( glMapBufferRange( GL_COPY_READ_BUFFER, 0, screen_size, GL_MAP_READ_BIT)); //memcpy(ptr_dst, ptr_src, screen_size); glUnmapBuffer(GL_COPY_READ_BUFFER); //glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); } glBindTexture(GL_TEXTURE_2D, _showtime_tex); glTexImage2D( GL_TEXTURE_2D, 0, base::get_pfd(CAPTURE_PF)->_internal, get_wnd_width(), get_wnd_height(), 0, base::get_pfd(CAPTURE_PF)->_format, base::get_pfd(CAPTURE_PF)->_type, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); const double map_time = _timer.elapsed_time(); __int64 result[3]={0,}; glGetQueryObjecti64v(sc->_queries[2], GL_QUERY_RESULT, result + 2); glGetQueryObjecti64v(sc->_queries[1], GL_QUERY_RESULT, result + 1); glGetQueryObjecti64v(sc->_queries[0], GL_QUERY_RESULT, result); const double coef_n2m = 1.0 / 1000000.0; const double time0 = double(result[1] - result[0]) * coef_n2m; const double time1 = double(result[2] - result[1]) * coef_n2m; static int counter = 0; if((counter++ % 64) == 0) { printf("read %.2f ms / %.2f GB/s copy: %.2f ms / %.2f GB/s lag: %u map: %.2f ms / %.2f GB/s\n", time0, (double(screen_size) / time0) * (1.0 / double(0x100000)), time1, time1 > 0.01 ? (double(screen_size) / time1) * (1.0 / double(0x100000)) : 0.0, _frame_number - sc->_frame_num, map_time, map_time > 0.01 ? (double(screen_size) / map_time) * (1.0 / double(0x100000)) : 0.0); } _rb_tail = tmp_tail; } else { break; } } }
enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; float white[] = {1, 1, 1, 1}; unsigned i, vbo, size; size_t page_size; GLsync fence = 0; float x, y, *mem; page_size = piglit_get_page_size(); size = ALIGN(NUM_PRIMS * TRI_SIZE, page_size); mem = piglit_alloc_aligned(page_size, size); glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); glGenBuffers(1, &vbo); glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, vbo); glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, mem, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexPointer(2, GL_FLOAT, 0, 0); x = 0, y = 0; for (i = 0; i < NUM_PRIMS; i++) { unsigned slot = 0; switch (test_offset) { case TEST_OFFSET_0_FENCE_WAIT: if (fence) glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); break; case TEST_OFFSET_INCR_NO_WAIT: slot = i; break; case TEST_OFFSET_DECR_NO_WAIT: slot = NUM_PRIMS - 1 - i; break; default: assert(0); } upload(vbo, mem, slot, x, y, x+20, y+20); glDrawArrays(GL_TRIANGLES, slot*3, 3); x += 20; if (x >= piglit_width) { x = 0; y += 20; } if (test_offset == TEST_OFFSET_0_FENCE_WAIT) { if (fence) glDeleteSync(fence); fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } } x = 0, y = 0; for (i = 0; i < NUM_PRIMS; i++) { GLboolean result = piglit_probe_pixel_rgb(x+5, y+5, white); if (!result) printf(" ... FAIL with primitive %i:\n", i+1); pass = result && pass; x += 20; if (x >= piglit_width) { x = 0; y += 20; } } if (fence) glDeleteSync(fence); glDeleteBuffers(1, &vbo); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; GLenum wait_val; GLsync sync; glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glColor3f(.8,0,0); glVertex3f(-0.9, -0.9, -30.0); glColor3f(0,.9,0); glVertex3f( 0.9, -0.9, -30.0); glColor3f(0,0,.7); glVertex3f( 0.0, 0.9, -30.0); glEnd(); glGetError(); sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); FAIL_ON_ERROR("glFenceSync"); if (!glIsSync(sync)) { fprintf(stderr, "IsSync(%p) failed\n", sync); pass = GL_FALSE; goto done; } FAIL_ON_ERROR("glIsSync"); if (! test_GetSynciv(sync, GL_SYNC_CONDITION, GL_SYNC_GPU_COMMANDS_COMPLETE)) { pass = GL_FALSE; goto done; } if (! test_GetSynciv(sync, GL_SYNC_FLAGS, 0)) { pass = GL_FALSE; goto done; } glFinish(); /* After the glFinish, the sync *must* be signaled! */ if (! test_GetSynciv(sync, GL_SYNC_STATUS, GL_SIGNALED)) { pass = GL_FALSE; goto done; } /* Since the sync has already been signaled, the wait should return * GL_ALREADY_SIGNALED. */ wait_val = glClientWaitSync(sync, 0, 1); FAIL_ON_ERROR("glClientWaitSync"); if (wait_val != GL_ALREADY_SIGNALED) { fprintf(stderr, "glClientWaitSync expected 0x%08x, " "got 0x%08x\n", GL_ALREADY_SIGNALED, wait_val); pass = GL_FALSE; } glDeleteSync(sync); FAIL_ON_ERROR("glDeleteSync"); done: return pass ? PIGLIT_PASS : PIGLIT_FAIL; }