Skip to content

Commit

Permalink
Reland "WIP: Optimize default framebuffer's drawable obtaining step"
Browse files Browse the repository at this point in the history
Defer the actual obtaining until first framebuffer's drawing/reading.

Change-Id: I1bd658cc5350cf52d6462016399455de57702ccf
  • Loading branch information
kakashidinho committed Nov 19, 2019
1 parent ab8ca84 commit e7109e7
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 210 deletions.
12 changes: 4 additions & 8 deletions src/libANGLE/renderer/metal/ContextMtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class DisplayMtl;
class FramebufferMtl;
class VertexArrayMtl;
class ProgramMtl;
class RenderTargetMtl;

class ContextMtl : public ContextImpl, public mtl::Context
{
Expand Down Expand Up @@ -231,25 +232,20 @@ class ContextMtl : public ContextImpl, public mtl::Context

// Check whether compatible render pass has been started.
bool hasStartedRenderPass(const mtl::RenderPassDesc &desc);
bool hasStartedRenderPass(FramebufferMtl *framebuffer);

// Get current render encoder. May be nullptr if no render pass has been started.
mtl::RenderCommandEncoder *getRenderCommandEncoder();

mtl::RenderCommandEncoder *getCurrentFramebufferRenderCommandEncoder();

// Will end current command encoder if it is valid, then start new encoder.
// Unless hasStartedRenderPass(desc) returns true.
mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::RenderPassDesc &desc);

// Utilities to quickly create render command enconder to a specific texture:
// Utilities to quickly create render command encoder to a specific texture:
// The previous content of texture will be loaded if clearColor is not provided
mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
const gl::ImageIndex &index,
mtl::RenderCommandEncoder *getRenderCommandEncoder(const RenderTargetMtl &renderTarget,
const Optional<MTLClearColor> &clearColor);
// The previous content of texture will be loaded
mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
const gl::ImageIndex &index);
mtl::RenderCommandEncoder *getRenderCommandEncoder(const RenderTargetMtl &renderTarget);

// Will end current command encoder and start new blit command encoder. Unless a blit comamnd
// encoder is already started.
Expand Down
53 changes: 16 additions & 37 deletions src/libANGLE/renderer/metal/ContextMtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@
// Framebuffer creation
FramebufferImpl *ContextMtl::createFramebuffer(const gl::FramebufferState &state)
{
return new FramebufferMtl(state, false);
return new FramebufferMtl(state, false, nullptr);
}

// Texture creation
Expand Down Expand Up @@ -1003,7 +1003,7 @@
ensureCommandBufferValid();

// Always discard default FBO's depth stencil buffers at the end of the frame:
if (mDrawFramebufferIsDefault && hasStartedRenderPass(mDrawFramebuffer))
if (mDrawFramebufferIsDefault && mDrawFramebuffer->renderPassHasStarted(this))
{
constexpr GLenum dsAttachments[] = {GL_DEPTH, GL_STENCIL};
(void)mDrawFramebuffer->invalidate(context, 2, dsAttachments);
Expand Down Expand Up @@ -1037,11 +1037,6 @@
mRenderEncoder.renderPassDesc().equalIgnoreLoadStoreOptions(desc);
}

bool ContextMtl::hasStartedRenderPass(FramebufferMtl *framebuffer)
{
return framebuffer && hasStartedRenderPass(framebuffer->getRenderPassDesc(this));
}

// Get current render encoder
mtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder()
{
Expand All @@ -1053,16 +1048,6 @@
return &mRenderEncoder;
}

mtl::RenderCommandEncoder *ContextMtl::getCurrentFramebufferRenderCommandEncoder()
{
if (!mDrawFramebuffer)
{
return nullptr;
}

return getRenderCommandEncoder(mDrawFramebuffer->getRenderPassDesc(this));
}

mtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder(const mtl::RenderPassDesc &desc)
{
if (hasStartedRenderPass(desc))
Expand All @@ -1080,36 +1065,31 @@
return &mRenderEncoder.restart(desc);
}

// Utilities to quickly create render command enconder to a specific texture:
// Utilities to quickly create render command encoder to a specific texture:
// The previous content of texture will be loaded if clearColor is not provided
mtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder(
const mtl::TextureRef &textureTarget,
const gl::ImageIndex &index,
const RenderTargetMtl &renderTarget,
const Optional<MTLClearColor> &clearColor)
{
ASSERT(textureTarget && textureTarget->valid());
ASSERT(renderTarget.getTexture());

mtl::RenderPassDesc rpDesc;

rpDesc.colorAttachments[0].texture = textureTarget;
rpDesc.colorAttachments[0].level = index.getLevelIndex();
rpDesc.colorAttachments[0].slice = index.hasLayer() ? index.getLayerIndex() : 0;
rpDesc.numColorAttachments = 1;
renderTarget.toRenderPassAttachmentDesc(&rpDesc.colorAttachments[0]);
rpDesc.numColorAttachments = 1;

if (clearColor.valid())
{
rpDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
rpDesc.colorAttachments[0].clearColor =
mtl::EmulatedAlphaClearColor(clearColor.value(), textureTarget->getColorWritableMask());
rpDesc.colorAttachments[0].clearColor = mtl::EmulatedAlphaClearColor(
clearColor.value(), renderTarget.getTexture()->getColorWritableMask());
}

return getRenderCommandEncoder(rpDesc);
}
// The previous content of texture will be loaded
mtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
const gl::ImageIndex &index)
mtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder(const RenderTargetMtl &renderTarget)
{
return getRenderCommandEncoder(textureTarget, index, Optional<MTLClearColor>());
return getRenderCommandEncoder(renderTarget, Optional<MTLClearColor>());
}

mtl::BlitCommandEncoder *ContextMtl::getBlitCommandEncoder()
Expand Down Expand Up @@ -1354,8 +1334,7 @@
if (mDirtyBits.test(DIRTY_BIT_DRAW_FRAMEBUFFER))
{
// Start new render command encoder
const mtl::RenderPassDesc &rpDesc = mDrawFramebuffer->getRenderPassDesc(this);
ANGLE_MTL_TRY(this, getRenderCommandEncoder(rpDesc));
ANGLE_MTL_TRY(this, mDrawFramebuffer->ensureRenderPassStarted(context));

// re-apply everything
invalidateState(context);
Expand Down Expand Up @@ -1552,15 +1531,15 @@

// Need to handle the case when render pass doesn't have depth/stencil attachment.
mtl::DepthStencilDesc dsDesc = mDepthStencilDesc;
const mtl::RenderPassDesc &renderPassDesc = mDrawFramebuffer->getRenderPassDesc(this);
const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc();

if (!renderPassDesc.depthAttachment.texture)
if (!renderPassDesc.depthAttachment.texture())
{
dsDesc.depthWriteEnabled = false;
dsDesc.depthCompareFunction = MTLCompareFunctionAlways;
}

if (!renderPassDesc.stencilAttachment.texture)
if (!renderPassDesc.stencilAttachment.texture())
{
dsDesc.frontFaceStencil.reset();
dsDesc.backFaceStencil.reset();
Expand Down Expand Up @@ -1606,7 +1585,7 @@

if (rppChange)
{
const mtl::RenderPassDesc &renderPassDesc = mDrawFramebuffer->getRenderPassDesc(this);
const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc();
// Obtain RenderPipelineDesc's output descriptor.
renderPassDesc.populateRenderPipelineOutputDesc(mBlendDesc,
&mRenderPipelineDesc.outputDescriptor);
Expand Down
20 changes: 15 additions & 5 deletions src/libANGLE/renderer/metal/FrameBufferMtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@

namespace rx
{
namespace mtl
{
class RenderCommandEncoder;
}
class ContextMtl;
class SurfaceMtl;

class FramebufferMtl : public FramebufferImpl
{
public:
explicit FramebufferMtl(const gl::FramebufferState &state, bool flipY);
explicit FramebufferMtl(const gl::FramebufferState &state, bool flipY, SurfaceMtl *backbuffer);
~FramebufferMtl() override;
void destroy(const gl::Context *context) override;

Expand Down Expand Up @@ -81,19 +85,20 @@ class FramebufferMtl : public FramebufferImpl
size_t index,
GLfloat *xy) const override;

RenderTargetMtl *getColorReadRenderTarget() const;
RenderTargetMtl *getColorReadRenderTarget(const gl::Context *context) const;

bool flipY() const { return mFlipY; }

gl::Rectangle getCompleteRenderArea() const;

const mtl::RenderPassDesc &getRenderPassDesc(ContextMtl *context);
bool renderPassHasStarted(ContextMtl *contextMtl) const;
mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context);

// Call this to notify FramebufferMtl whenever its render pass has started.
void onStartedDrawingToFrameBuffer(const gl::Context *context);

// The actual area will be adjusted based on framebuffer flipping property.
gl::Rectangle getReadPixelArea(const gl::Rectangle &glArea);
gl::Rectangle getReadPixelArea(const gl::Context *context, const gl::Rectangle &glArea);

// NOTE: this method doesn't do the flipping of area. Caller must do it if needed before
// callling this. See getReadPixelsArea().
Expand Down Expand Up @@ -122,6 +127,9 @@ class FramebufferMtl : public FramebufferImpl
gl::DrawBufferMask drawColorBuffers,
mtl::RenderPassDesc *descOut);

mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context,
const mtl::RenderPassDesc &desc);

void overrideClearColor(const mtl::TextureRef &texture,
MTLClearColor clearColor,
MTLClearColor *colorOut);
Expand All @@ -140,7 +148,9 @@ class FramebufferMtl : public FramebufferImpl
RenderTargetMtl *mDepthRenderTarget = nullptr;
RenderTargetMtl *mStencilRenderTarget = nullptr;
mtl::RenderPassDesc mRenderPassDesc;
const bool mFlipY = false;

SurfaceMtl *mBackbuffer = nullptr;
const bool mFlipY = false;
};
} // namespace rx

Expand Down
Loading

0 comments on commit e7109e7

Please sign in to comment.