Bug 1500017 - Use triple buffer with DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL SwapChain r=mattwoodrow

This commit is contained in:
sotaro
2018-11-05 15:54:10 +09:00
parent acbc160eae
commit 9b8ec03f62
12 changed files with 116 additions and 24 deletions

View File

@@ -31,6 +31,7 @@ AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
AsyncImagePipelineManager::AsyncImagePipelineManager(already_AddRefed<wr::WebRenderAPI>&& aApi)
: mApi(aApi)
, mIdNamespace(mApi->GetNamespace())
, mUseTripleBuffering(mApi->GetUseTripleBuffering())
, mResourceId(0)
, mAsyncImageEpoch{0}
, mWillGenerateFrame(false)
@@ -550,8 +551,6 @@ AsyncImagePipelineManager::NotifyPipelinesUpdated(wr::WrPipelineInfo aInfo, bool
MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
// Increment the count when render happens.
// XXX The count is going to be used to delay releasing TextureHosts for multiple rendering.
// See Bug 1500017.
uint64_t currCount = aRender ? ++mUpdatesCount : mUpdatesCount;
auto updates = MakeUnique<PipelineUpdates>(currCount, aRender);
@@ -630,15 +629,16 @@ AsyncImagePipelineManager::ProcessPipelineUpdates()
updates->mQueue.pop();
if (epoch.isSome()) {
ProcessPipelineRendered(pipelineId, *epoch);
ProcessPipelineRendered(pipelineId, *epoch, updates->mUpdatesCount);
} else {
ProcessPipelineRemoved(pipelineId);
ProcessPipelineRemoved(pipelineId, updates->mUpdatesCount);
}
}
CheckForTextureHostsNotUsedByGPU();
}
void
AsyncImagePipelineManager::ProcessPipelineRendered(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
AsyncImagePipelineManager::ProcessPipelineRendered(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, const uint64_t aUpdatesCount)
{
if (auto entry = mPipelineTexturesHolders.Lookup(wr::AsUint64(aPipelineId))) {
PipelineTexturesHolder* holder = entry.Data();
@@ -647,6 +647,8 @@ AsyncImagePipelineManager::ProcessPipelineRendered(const wr::PipelineId& aPipeli
if (aEpoch <= holder->mTextureHosts.front().mEpoch) {
break;
}
// Need to extend holding TextureHost if it is direct bounded texture.
HoldUntilNotUsedByGPU(holder->mTextureHosts.front().mTexture, aUpdatesCount);
holder->mTextureHosts.pop();
}
while (!holder->mTextureHostWrappers.empty()) {
@@ -668,7 +670,7 @@ AsyncImagePipelineManager::ProcessPipelineRendered(const wr::PipelineId& aPipeli
}
void
AsyncImagePipelineManager::ProcessPipelineRemoved(const wr::PipelineId& aPipelineId)
AsyncImagePipelineManager::ProcessPipelineRemoved(const wr::PipelineId& aPipelineId, const uint64_t aUpdatesCount)
{
if (mDestroyed) {
return;
@@ -676,6 +678,11 @@ AsyncImagePipelineManager::ProcessPipelineRemoved(const wr::PipelineId& aPipelin
if (auto entry = mPipelineTexturesHolders.Lookup(wr::AsUint64(aPipelineId))) {
PipelineTexturesHolder* holder = entry.Data();
if (holder->mDestroyedEpoch.isSome()) {
while (!holder->mTextureHosts.empty()) {
// Need to extend holding TextureHost if it is direct bounded texture.
HoldUntilNotUsedByGPU(holder->mTextureHosts.front().mTexture, aUpdatesCount);
holder->mTextureHosts.pop();
}
// Explicitly release all of the shared surfaces.
while (!holder->mExternalImages.empty()) {
DebugOnly<bool> released =
@@ -692,6 +699,39 @@ AsyncImagePipelineManager::ProcessPipelineRemoved(const wr::PipelineId& aPipelin
}
}
void
AsyncImagePipelineManager::HoldUntilNotUsedByGPU(const CompositableTextureHostRef& aTextureHost, uint64_t aUpdatesCount)
{
MOZ_ASSERT(aTextureHost);
if (aTextureHost->HasIntermediateBuffer()) {
// If texutre is not direct binding texture, gpu has already finished using it.
// We could release it now.
return;
}
// When Triple buffer is used, we need wait one more WebRender rendering,
if (mUseTripleBuffering) {
++aUpdatesCount;
}
mTexturesInUseByGPU.emplace(
std::make_pair(aUpdatesCount, aTextureHost));
}
void
AsyncImagePipelineManager::CheckForTextureHostsNotUsedByGPU()
{
uint64_t currCount = mUpdatesCount;
while (!mTexturesInUseByGPU.empty()) {
if (currCount <= mTexturesInUseByGPU.front().first) {
break;
}
mTexturesInUseByGPU.pop();
}
}
wr::Epoch
AsyncImagePipelineManager::GetNextImageEpoch()
{