1bdf2d80f459d43f5a6df074431bacf41584f81b7shannon.woods@transgaming.com#include "precompiled.h" 2d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org// 35defc5c0d5c53456d37992fe7ac14af493c12d17shannon.woods@transgaming.com// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 4d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org// Use of this source code is governed by a BSD-style license that can be 5d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org// found in the LICENSE file. 6d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org// 7d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 8d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. 9d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 10cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// Important note on accurate timers in Windows: 11cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// 12cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call 13cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// as timeGetTime on laptops and "jumping" during certain hardware events. 14cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// 15cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" 16cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc 17cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// 18cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer 19cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill// from buggy implementations. 20cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 21d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org#include "libGLESv2/Fence.h" 225defc5c0d5c53456d37992fe7ac14af493c12d17shannon.woods@transgaming.com#include "libGLESv2/renderer/FenceImpl.h" 23486d9e9b6b4ed31f66d2624b8e822020fe40a1f7shannon.woods@transgaming.com#include "libGLESv2/renderer/Renderer.h" 2409752369e814a809e3033973aa294ede4b4fb9bcJamie Madill#include "libGLESv2/main.h" 25d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 26d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.orgnamespace gl 27d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 28d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 2933dc84394ba08700d700a3da692e8de18433a031Jamie MadillFenceNV::FenceNV(rx::Renderer *renderer) 30563c0a533544792bb1df86338866a5d38d749597apatrick@chromium.org{ 315defc5c0d5c53456d37992fe7ac14af493c12d17shannon.woods@transgaming.com mFence = renderer->createFence(); 32d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 33d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 3433dc84394ba08700d700a3da692e8de18433a031Jamie MadillFenceNV::~FenceNV() 35d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 365defc5c0d5c53456d37992fe7ac14af493c12d17shannon.woods@transgaming.com delete mFence; 37d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 38d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 3933dc84394ba08700d700a3da692e8de18433a031Jamie MadillGLboolean FenceNV::isFence() const 40d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 4109752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // GL_NV_fence spec: 4209752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. 4309752369e814a809e3033973aa294ede4b4fb9bcJamie Madill return (mFence->isSet() ? GL_TRUE : GL_FALSE); 44d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 45d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 4633dc84394ba08700d700a3da692e8de18433a031Jamie Madillvoid FenceNV::setFence(GLenum condition) 47d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 4809752369e814a809e3033973aa294ede4b4fb9bcJamie Madill mFence->set(); 4909752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 5009752369e814a809e3033973aa294ede4b4fb9bcJamie Madill mCondition = condition; 5109752369e814a809e3033973aa294ede4b4fb9bcJamie Madill mStatus = GL_FALSE; 52d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 53d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 5433dc84394ba08700d700a3da692e8de18433a031Jamie MadillGLboolean FenceNV::testFence() 55d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 5609752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // Flush the command buffer by default 5709752369e814a809e3033973aa294ede4b4fb9bcJamie Madill bool result = mFence->test(true); 5809752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 5909752369e814a809e3033973aa294ede4b4fb9bcJamie Madill mStatus = (result ? GL_TRUE : GL_FALSE); 6009752369e814a809e3033973aa294ede4b4fb9bcJamie Madill return mStatus; 61d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 62d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 6333dc84394ba08700d700a3da692e8de18433a031Jamie Madillvoid FenceNV::finishFence() 64d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 65fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill ASSERT(mFence->isSet()); 6609752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 6709752369e814a809e3033973aa294ede4b4fb9bcJamie Madill while (!mFence->test(true)) 6809752369e814a809e3033973aa294ede4b4fb9bcJamie Madill { 6909752369e814a809e3033973aa294ede4b4fb9bcJamie Madill Sleep(0); 7009752369e814a809e3033973aa294ede4b4fb9bcJamie Madill } 71d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 72d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 7333dc84394ba08700d700a3da692e8de18433a031Jamie MadillGLint FenceNV::getFencei(GLenum pname) 74d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org{ 75fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill ASSERT(mFence->isSet()); 7609752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 7709752369e814a809e3033973aa294ede4b4fb9bcJamie Madill switch (pname) 7809752369e814a809e3033973aa294ede4b4fb9bcJamie Madill { 7909752369e814a809e3033973aa294ede4b4fb9bcJamie Madill case GL_FENCE_STATUS_NV: 8009752369e814a809e3033973aa294ede4b4fb9bcJamie Madill { 8109752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // GL_NV_fence spec: 8209752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV 8309752369e814a809e3033973aa294ede4b4fb9bcJamie Madill // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. 8409752369e814a809e3033973aa294ede4b4fb9bcJamie Madill if (mStatus == GL_TRUE) 8509752369e814a809e3033973aa294ede4b4fb9bcJamie Madill { 86fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill return GL_TRUE; 8709752369e814a809e3033973aa294ede4b4fb9bcJamie Madill } 8809752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 8909752369e814a809e3033973aa294ede4b4fb9bcJamie Madill mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE); 90fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill return mStatus; 9109752369e814a809e3033973aa294ede4b4fb9bcJamie Madill } 9209752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 9309752369e814a809e3033973aa294ede4b4fb9bcJamie Madill case GL_FENCE_CONDITION_NV: 94fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill return mCondition; 9509752369e814a809e3033973aa294ede4b4fb9bcJamie Madill 96fb9a7409515cb0a8f9926974511ff486361909d7Jamie Madill default: UNREACHABLE(); return 0; 9709752369e814a809e3033973aa294ede4b4fb9bcJamie Madill } 98d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 99d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org 100cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie MadillFenceSync::FenceSync(rx::Renderer *renderer, GLuint id) 101cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill : RefCountObject(id) 102cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 103cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill mFence = renderer->createFence(); 104cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 105d21656c1fbdb761428e99309d28e1787196e359dGeoff Lang LARGE_INTEGER counterFreqency = { 0 }; 106af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens BOOL success = QueryPerformanceFrequency(&counterFreqency); 1079cd1915c96800fc998ec25b88b0e3081f0aa6109Geoff Lang UNUSED_ASSERTION_VARIABLE(success); 108af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens ASSERT(success); 109cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 110cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill mCounterFrequency = counterFreqency.QuadPart; 111cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 112cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 113cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie MadillFenceSync::~FenceSync() 114cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 115cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill delete mFence; 116cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 117cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 118cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madillvoid FenceSync::set(GLenum condition) 119cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 120cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill mCondition = condition; 121cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill mFence->set(); 122cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 123cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 124cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie MadillGLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout) 125cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 126cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill ASSERT(mFence->isSet()); 127cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 128cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); 129cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 130cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (mFence->test(flushCommandBuffer)) 131cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 132cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_ALREADY_SIGNALED; 133cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 134cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 135cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (mFence->hasError()) 136cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 137cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_WAIT_FAILED; 138cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 139cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 140cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (timeout == 0) 141cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 142cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_TIMEOUT_EXPIRED; 143cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 144cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 145d21656c1fbdb761428e99309d28e1787196e359dGeoff Lang LARGE_INTEGER currentCounter = { 0 }; 146af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens BOOL success = QueryPerformanceCounter(¤tCounter); 1479cd1915c96800fc998ec25b88b0e3081f0aa6109Geoff Lang UNUSED_ASSERTION_VARIABLE(success); 148af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens ASSERT(success); 149cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 150cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll); 151cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; 152cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 153cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer)) 154cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 155cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill Sleep(0); 156af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens BOOL success = QueryPerformanceCounter(¤tCounter); 1579cd1915c96800fc998ec25b88b0e3081f0aa6109Geoff Lang UNUSED_ASSERTION_VARIABLE(success); 158af88d7290afacb0a8abd13d331f7ed7290d4918bNicolas Capens ASSERT(success); 159cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 160cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 161cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (mFence->hasError()) 162cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 163cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_WAIT_FAILED; 164cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 165cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 166cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (currentCounter.QuadPart >= endCounter) 167cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 168cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_TIMEOUT_EXPIRED; 169cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 170cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 171cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_CONDITION_SATISFIED; 172cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 173cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 174cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madillvoid FenceSync::serverWait() 175cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 176cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill // Because our API is currently designed to be called from a single thread, we don't need to do 177cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill // extra work for a server-side fence. GPU commands issued after the fence is created will always 178cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill // be processed after the fence is signaled. 179cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 180cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 181cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie MadillGLenum FenceSync::getStatus() const 182cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill{ 183cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill if (mFence->test(false)) 184cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill { 185cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill // The spec does not specify any way to report errors during the status test (e.g. device lost) 186cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill // so we report the fence is unblocked in case of error or signaled. 187cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_SIGNALED; 188cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill } 189cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 190cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill return GL_UNSIGNALED; 191cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill} 192cd055f81f941b108b936fa0eaf2523793ddf7b4fJamie Madill 193d3bd0ad320fb246d9b42a0161c27eeb56c7e9160apatrick@chromium.org} 194