Add a helper for automating ClearView and clear-shader operations. (bug 1378095 part 1, r=mattwoodrow)

This commit is contained in:
David Anderson 2017-07-13 01:11:58 -07:00
parent d11ba73bee
commit ddfbc3d0ae
7 changed files with 114 additions and 57 deletions

View File

@ -304,7 +304,6 @@ private:
RefPtr<IDXGIResource> mSyncTexture;
HANDLE mSyncHandle;
RefPtr<MLGRenderTarget> mCurrentRT;
RefPtr<MLGBuffer> mUnitQuadVB;
RefPtr<MLGBuffer> mUnitTriangleVB;
RefPtr<ID3D11VertexShader> mCurrentVertexShader;

View File

@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_gfx_layers_mlgpu_ClearRegionHelper_h
#define mozilla_gfx_layers_mlgpu_ClearRegionHelper_h
#include "SharedBufferMLGPU.h"
namespace mozilla {
namespace layers {
// This is a helper class for issuing a clear operation based on either
// a shader or an API like ClearView. It also works when the depth
// buffer is enabled.
struct ClearRegionHelper
{
// If using ClearView-based clears, we fill mRegions.
nsTArray<gfx::IntRect> mRects;
// If using shader-based clears, we fill these buffers.
VertexBufferSection mInput;
ConstantBufferSection mVSBuffer;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_gfx_layers_mlgpu_ClearRegionHelper_h

View File

@ -6,6 +6,7 @@
#include "MLGDevice.h"
#include "mozilla/layers/TextureHost.h"
#include "BufferCache.h"
#include "ClearRegionHelper.h"
#include "gfxConfig.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
@ -170,7 +171,7 @@ MLGDevice::SetTopology(MLGPrimitiveTopology aTopology)
}
void
MLGDevice::SetVertexBuffer(uint32_t aSlot, VertexBufferSection* aSection)
MLGDevice::SetVertexBuffer(uint32_t aSlot, const VertexBufferSection* aSection)
{
if (!aSection->IsValid()) {
return;
@ -179,7 +180,7 @@ MLGDevice::SetVertexBuffer(uint32_t aSlot, VertexBufferSection* aSection)
}
void
MLGDevice::SetPSConstantBuffer(uint32_t aSlot, ConstantBufferSection* aSection)
MLGDevice::SetPSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection)
{
if (!aSection->IsValid()) {
return;
@ -197,7 +198,7 @@ MLGDevice::SetPSConstantBuffer(uint32_t aSlot, ConstantBufferSection* aSection)
}
void
MLGDevice::SetVSConstantBuffer(uint32_t aSlot, ConstantBufferSection* aSection)
MLGDevice::SetVSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection)
{
if (!aSection->IsValid()) {
return;
@ -310,5 +311,48 @@ MLGDevice::Synchronize()
return true;
}
void
MLGDevice::PrepareClearRegion(ClearRegionHelper* aOut,
nsTArray<gfx::IntRect>&& aRects,
const Maybe<int32_t>& aSortIndex)
{
if (CanUseClearView() && !aSortIndex) {
aOut->mRects = Move(aRects);
return;
}
mSharedVertexBuffer->Allocate(
&aOut->mInput,
aRects.Length(),
sizeof(IntRect),
aRects.Elements());
ClearConstants consts(aSortIndex ? aSortIndex.value() : 1);
mSharedVSBuffer->Allocate(&aOut->mVSBuffer, consts);
}
void
MLGDevice::DrawClearRegion(const ClearRegionHelper& aHelper)
{
// If we've set up vertices for a shader-based clear, execute that now.
if (aHelper.mInput.IsValid()) {
SetTopology(MLGPrimitiveTopology::UnitQuad);
SetVertexShader(VertexShaderID::Clear);
SetVertexBuffer(1, &aHelper.mInput);
SetVSConstantBuffer(kClearConstantBufferSlot, &aHelper.mVSBuffer);
SetBlendState(MLGBlendState::Copy);
SetPixelShader(PixelShaderID::Clear);
DrawInstanced(4, aHelper.mInput.NumVertices(), 0, 0);
return;
}
// Otherwise, if we have a normal rect list, we wanted to use the faster
// ClearView.
if (!aHelper.mRects.IsEmpty()) {
Color color(0.0, 0.0, 0.0, 0.0);
ClearView(mCurrentRT, color, aHelper.mRects.Elements(), aHelper.mRects.Length());
}
}
} // namespace layers
} // namespace mozilla

View File

@ -45,6 +45,7 @@ class SharedVertexBuffer;
class SharedConstantBuffer;
class TextureSource;
class VertexBufferSection;
struct ClearRegionHelper;
class MLGRenderTarget
{
@ -349,9 +350,9 @@ public:
virtual MLGDeviceD3D11* AsD3D11() { return nullptr; }
// Helpers.
void SetVertexBuffer(uint32_t aSlot, VertexBufferSection* aSection);
void SetPSConstantBuffer(uint32_t aSlot, ConstantBufferSection* aSection);
void SetVSConstantBuffer(uint32_t aSlot, ConstantBufferSection* aSection);
void SetVertexBuffer(uint32_t aSlot, const VertexBufferSection* aSection);
void SetPSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection);
void SetVSConstantBuffer(uint32_t aSlot, const ConstantBufferSection* aSection);
void SetPSTexture(uint32_t aSlot, TextureSource* aSource);
void SetSamplerMode(uint32_t aIndex, gfx::SamplingFilter aFilter);
@ -392,6 +393,14 @@ public:
return mFailureMessage;
}
// Prepare a clear-region operation to be run at a later time.
void PrepareClearRegion(ClearRegionHelper* aOut,
nsTArray<gfx::IntRect>&& aRects,
const Maybe<int32_t>& aSortIndex);
// Execute a clear-region operation. This may change shader state.
void DrawClearRegion(const ClearRegionHelper& aHelper);
// If supported, synchronize with the SyncObject given to clients.
virtual bool Synchronize();
@ -475,6 +484,8 @@ protected:
bool mCanUseClearView;
bool mCanUseConstantBufferOffsetBinding;
size_t mMaxConstantBufferBindSize;
RefPtr<MLGRenderTarget> mCurrentRT;
};
} // namespace layers

View File

@ -400,7 +400,7 @@ RenderViewMLGPU::ExecuteRendering()
// Clear any pixels that are not occluded, and therefore might require
// blending.
DrawClear();
mDevice->DrawClearRegion(mClear);
// Render back-to-front passes.
for (auto iter = mBackToFront.begin(); iter != mBackToFront.end(); iter++) {
@ -498,51 +498,16 @@ RenderViewMLGPU::PrepareClear()
region.SubOut(mOccludedRegion);
region.SimplifyOutward(kMaxClearViewRects);
}
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
mClearRects.AppendElement(iter.Get().ToUnknownRect());
Maybe<int32_t> sortIndex;
if (mUseDepthBuffer) {
// Note that we use the lowest available sorting index, to ensure that when
// using the z-buffer, we don't draw over already-drawn content.
sortIndex = Some(mNextSortIndex++);
}
// If ClearView is supported and we're not using a depth buffer, we
// can stop here. We'll use the rects as inputs to ClearView.
if (mClearRects.IsEmpty() || (mDevice->CanUseClearView() && !mUseDepthBuffer)) {
return;
}
// Set up vertices for a shader-based clear.
mDevice->GetSharedVertexBuffer()->Allocate(
&mClearInput,
mClearRects.Length(),
sizeof(IntRect),
mClearRects.Elements());
mClearRects.Clear();
// Note that we use the lowest available sorting index, to ensure that when
// using the z-buffer, we don't draw over already-drawn content.
ClearConstants consts(mNextSortIndex++);
mDevice->GetSharedVSBuffer()->Allocate(&mClearConstants, consts);
}
void
RenderViewMLGPU::DrawClear()
{
// If we've set up vertices for a shader-based clear, execute that now.
if (mClearInput.IsValid()) {
mDevice->SetTopology(MLGPrimitiveTopology::UnitQuad);
mDevice->SetVertexShader(VertexShaderID::Clear);
mDevice->SetVertexBuffer(1, &mClearInput);
mDevice->SetVSConstantBuffer(kClearConstantBufferSlot, &mClearConstants);
mDevice->SetBlendState(MLGBlendState::Copy);
mDevice->SetPixelShader(PixelShaderID::Clear);
mDevice->DrawInstanced(4, mClearInput.NumVertices(), 0, 0);
return;
}
// Otherwise, if we have a normal rect list, we wanted to use the faster
// ClearView.
if (!mClearRects.IsEmpty()) {
Color color(0.0, 0.0, 0.0, 0.0);
mDevice->ClearView(mTarget, color, mClearRects.Elements(), mClearRects.Length());
}
nsTArray<IntRect> rects = ToRectArray(region);
mDevice->PrepareClearRegion(&mClear, Move(rects), sortIndex);
}
} // namespace layers

View File

@ -7,6 +7,7 @@
#define mozilla_gfx_layers_mlgpu_RenderViewMLGPU_h
#include "LayerManagerMLGPU.h"
#include "ClearRegionHelper.h"
#include "RenderPassMLGPU.h"
#include "Units.h"
#include <deque>
@ -90,12 +91,8 @@ private:
// Shader data.
ConstantBufferSection mWorldConstants;
// If using ClearView-based clears.
nsTArray<gfx::IntRect> mClearRects;
// If using shader-based clears.
VertexBufferSection mClearInput;
ConstantBufferSection mClearConstants;
// Information for the initial target surface clear.
ClearRegionHelper mClear;
// Either an MLGSwapChain-derived render target, or an intermediate surface.
RefPtr<MLGRenderTarget> mTarget;

View File

@ -95,6 +95,17 @@ struct BlendVertexShaderConstants {
float backdropTransform[4][4];
};
template <typename T>
static inline nsTArray<gfx::IntRect>
ToRectArray(const T& aRegion)
{
nsTArray<gfx::IntRect> rects;
for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
rects.AppendElement(iter.Get().ToUnknownRect());
}
return rects;
}
struct SimpleTraits
{
explicit SimpleTraits(const ItemInfo& aItem, const gfx::Rect& aRect)