mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 01:35:35 +00:00
Bug 1506091 - Wait for GPU after posting NotifyDidRender r=mattwoodrow
This commit is contained in:
parent
1799f77b76
commit
8013630c8b
@ -544,7 +544,7 @@ AsyncImagePipelineManager::HoldExternalImage(const wr::PipelineId& aPipelineId,
|
||||
}
|
||||
|
||||
void
|
||||
AsyncImagePipelineManager::NotifyPipelinesUpdated(wr::WrPipelineInfo aInfo, bool aRender)
|
||||
AsyncImagePipelineManager::NotifyPipelinesUpdated(const wr::WrPipelineInfo& aInfo, bool aRender)
|
||||
{
|
||||
// This is called on the render thread, so we just stash the data into
|
||||
// UpdatesQueue and process it later on the compositor thread.
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
// This is called from the Renderer thread to notify this class about the
|
||||
// pipelines in the most recently completed render. A copy of the update
|
||||
// information is put into mUpdatesQueue.
|
||||
void NotifyPipelinesUpdated(wr::WrPipelineInfo aInfo, bool aRender);
|
||||
void NotifyPipelinesUpdated(const wr::WrPipelineInfo& aInfo, bool aRender);
|
||||
|
||||
// This is run on the compositor thread to process mUpdatesQueue. We make
|
||||
// this a public entry point because we need to invoke it from other places.
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
|
||||
virtual bool BeginFrame() = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void WaitForGPU() = 0;
|
||||
virtual void Pause() = 0;
|
||||
virtual bool Resume() = 0;
|
||||
|
||||
|
@ -341,7 +341,11 @@ RenderCompositorANGLE::EndFrame()
|
||||
if (mCompositionDevice) {
|
||||
mCompositionDevice->Commit();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RenderCompositorANGLE::WaitForGPU()
|
||||
{
|
||||
// Note: this waits on the query we inserted in the previous frame,
|
||||
// not the one we just inserted now. Example:
|
||||
// Insert query #1
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
bool BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
void WaitForGPU() override;
|
||||
void Pause() override;
|
||||
bool Resume() override;
|
||||
|
||||
|
@ -53,6 +53,11 @@ RenderCompositorOGL::EndFrame()
|
||||
mGL->SwapBuffers();
|
||||
}
|
||||
|
||||
void
|
||||
RenderCompositorOGL::WaitForGPU()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RenderCompositorOGL::Pause()
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
|
||||
bool BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
void WaitForGPU() override;
|
||||
void Pause() override;
|
||||
bool Resume() override;
|
||||
|
||||
|
@ -340,7 +340,7 @@ RenderThread::RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent)
|
||||
|
||||
static void
|
||||
NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
||||
wr::WrPipelineInfo aInfo,
|
||||
RefPtr<WebRenderPipelineInfo> aInfo,
|
||||
TimeStamp aStart,
|
||||
TimeStamp aEnd,
|
||||
bool aRender)
|
||||
@ -352,15 +352,15 @@ NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
||||
aBridge->GetWrBridge()->RecordFrame();
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < aInfo.epochs.length; i++) {
|
||||
auto info = aInfo->Raw();
|
||||
|
||||
for (uintptr_t i = 0; i < info.epochs.length; i++) {
|
||||
aBridge->NotifyPipelineRendered(
|
||||
aInfo.epochs.data[i].pipeline_id,
|
||||
aInfo.epochs.data[i].epoch,
|
||||
info.epochs.data[i].pipeline_id,
|
||||
info.epochs.data[i].epoch,
|
||||
aStart,
|
||||
aEnd);
|
||||
}
|
||||
|
||||
wr_pipeline_info_delete(aInfo);
|
||||
}
|
||||
|
||||
void
|
||||
@ -382,9 +382,9 @@ RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
||||
}
|
||||
|
||||
auto& renderer = it->second;
|
||||
|
||||
bool rendered = false;
|
||||
if (aRender) {
|
||||
renderer->UpdateAndRender(aReadbackSize, aReadbackBuffer, aHadSlowFrame);
|
||||
rendered = renderer->UpdateAndRender(aReadbackSize, aReadbackBuffer, aHadSlowFrame);
|
||||
} else {
|
||||
renderer->Update();
|
||||
}
|
||||
@ -392,17 +392,7 @@ RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
||||
renderer->CheckGraphicsResetStatus();
|
||||
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
|
||||
auto info = renderer->FlushPipelineInfo();
|
||||
RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
|
||||
renderer->GetCompositorBridge()->GetAsyncImagePipelineManager();
|
||||
// pipelineMgr should always be non-null here because it is only nulled out
|
||||
// after the WebRenderAPI instance for the CompositorBridgeParent is
|
||||
// destroyed, and that destruction blocks until the renderer thread has
|
||||
// removed the relevant renderer. And after that happens we should never reach
|
||||
// this code at all; it would bail out at the mRenderers.find check above.
|
||||
MOZ_ASSERT(pipelineMgr);
|
||||
pipelineMgr->NotifyPipelinesUpdated(info, aRender);
|
||||
|
||||
layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
|
||||
"NotifyDidRenderRunnable",
|
||||
@ -412,6 +402,25 @@ RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
||||
aStartTime, end,
|
||||
aRender
|
||||
));
|
||||
|
||||
if (rendered) {
|
||||
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
||||
// necessary for the NotifyDidRender.
|
||||
// The wait is necessary for Textures recycling of AsyncImagePipelineManager
|
||||
// and for avoiding GPU queue is filled with too much tasks.
|
||||
// WaitForGPU's implementation is different for each platform.
|
||||
renderer->WaitForGPU();
|
||||
}
|
||||
|
||||
RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
|
||||
renderer->GetCompositorBridge()->GetAsyncImagePipelineManager();
|
||||
// pipelineMgr should always be non-null here because it is only nulled out
|
||||
// after the WebRenderAPI instance for the CompositorBridgeParent is
|
||||
// destroyed, and that destruction blocks until the renderer thread has
|
||||
// removed the relevant renderer. And after that happens we should never reach
|
||||
// this code at all; it would bail out at the mRenderers.find check above.
|
||||
MOZ_ASSERT(pipelineMgr);
|
||||
pipelineMgr->NotifyPipelinesUpdated(info->Raw(), aRender);
|
||||
}
|
||||
|
||||
void
|
||||
@ -795,6 +804,16 @@ WebRenderShaders::~WebRenderShaders() {
|
||||
wr_shaders_delete(mShaders, mGL.get());
|
||||
}
|
||||
|
||||
WebRenderPipelineInfo::WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo)
|
||||
: mPipelineInfo(aPipelineInfo)
|
||||
{
|
||||
}
|
||||
|
||||
WebRenderPipelineInfo::~WebRenderPipelineInfo()
|
||||
{
|
||||
wr_pipeline_info_delete(mPipelineInfo);
|
||||
}
|
||||
|
||||
WebRenderThreadPool::WebRenderThreadPool()
|
||||
{
|
||||
mThreadPool = wr_thread_pool_new();
|
||||
|
@ -72,6 +72,19 @@ protected:
|
||||
wr::WrShaders* mShaders;
|
||||
};
|
||||
|
||||
class WebRenderPipelineInfo {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo);
|
||||
public:
|
||||
explicit WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo);
|
||||
|
||||
const wr::WrPipelineInfo& Raw() { return mPipelineInfo; }
|
||||
|
||||
protected:
|
||||
~WebRenderPipelineInfo();
|
||||
|
||||
const wr::WrPipelineInfo mPipelineInfo;
|
||||
};
|
||||
|
||||
/// Base class for an event that can be scheduled to run on the render thread.
|
||||
///
|
||||
/// The event can be passed through the same channels as regular WebRender messages
|
||||
|
@ -194,6 +194,12 @@ RendererOGL::CheckGraphicsResetStatus()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RendererOGL::WaitForGPU()
|
||||
{
|
||||
mCompositor->WaitForGPU();
|
||||
}
|
||||
|
||||
void
|
||||
RendererOGL::Pause()
|
||||
{
|
||||
@ -229,10 +235,11 @@ RendererOGL::SetFrameStartTime(const TimeStamp& aTime)
|
||||
mFrameStartTime = aTime;
|
||||
}
|
||||
|
||||
wr::WrPipelineInfo
|
||||
RefPtr<WebRenderPipelineInfo>
|
||||
RendererOGL::FlushPipelineInfo()
|
||||
{
|
||||
return wr_renderer_flush_pipeline_info(mRenderer);
|
||||
auto info = wr_renderer_flush_pipeline_info(mRenderer);
|
||||
return new WebRenderPipelineInfo(info);
|
||||
}
|
||||
|
||||
RenderTextureHost*
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
bool UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<Range<uint8_t>>& aReadbackBuffer, bool aHadSlowFrame);
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
bool RenderToTarget(gfx::DrawTarget& aTarget);
|
||||
void WaitForGPU();
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
void SetProfilerEnabled(bool aEnabled);
|
||||
@ -91,7 +91,7 @@ public:
|
||||
|
||||
layers::CompositorBridgeParent* GetCompositorBridge() { return mBridge; }
|
||||
|
||||
wr::WrPipelineInfo FlushPipelineInfo();
|
||||
RefPtr<WebRenderPipelineInfo> FlushPipelineInfo();
|
||||
|
||||
RenderTextureHost* GetRenderTexture(wr::WrExternalImageId aExternalImageId);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user