From e7109e773098a63a855c0085865b758c38144e9e Mon Sep 17 00:00:00 2001 From: Le Hoang Quyen Date: Tue, 19 Nov 2019 03:04:00 +0800 Subject: [PATCH] Reland "WIP: Optimize default framebuffer's drawable obtaining step" Defer the actual obtaining until first framebuffer's drawing/reading. Change-Id: I1bd658cc5350cf52d6462016399455de57702ccf --- src/libANGLE/renderer/metal/ContextMtl.h | 12 +- src/libANGLE/renderer/metal/ContextMtl.mm | 53 +++------ src/libANGLE/renderer/metal/FrameBufferMtl.h | 20 +++- src/libANGLE/renderer/metal/FrameBufferMtl.mm | 80 ++++++++++--- src/libANGLE/renderer/metal/RenderTargetMtl.h | 16 +-- .../renderer/metal/RenderTargetMtl.mm | 36 +++--- src/libANGLE/renderer/metal/SurfaceMtl.h | 10 +- src/libANGLE/renderer/metal/SurfaceMtl.mm | 107 ++++++++---------- src/libANGLE/renderer/metal/TextureMtl.h | 7 +- src/libANGLE/renderer/metal/TextureMtl.mm | 45 ++++---- .../renderer/metal/mtl_command_buffer.mm | 6 +- .../renderer/metal/mtl_render_utils.mm | 24 ++-- src/libANGLE/renderer/metal/mtl_state_cache.h | 21 +++- .../renderer/metal/mtl_state_cache.mm | 19 ++-- 14 files changed, 246 insertions(+), 210 deletions(-) diff --git a/src/libANGLE/renderer/metal/ContextMtl.h b/src/libANGLE/renderer/metal/ContextMtl.h index a05bb880a1..670a7c9b1a 100644 --- a/src/libANGLE/renderer/metal/ContextMtl.h +++ b/src/libANGLE/renderer/metal/ContextMtl.h @@ -27,6 +27,7 @@ class DisplayMtl; class FramebufferMtl; class VertexArrayMtl; class ProgramMtl; +class RenderTargetMtl; class ContextMtl : public ContextImpl, public mtl::Context { @@ -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 &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. diff --git a/src/libANGLE/renderer/metal/ContextMtl.mm b/src/libANGLE/renderer/metal/ContextMtl.mm index 32c183f91a..f8eca9a246 100644 --- a/src/libANGLE/renderer/metal/ContextMtl.mm +++ b/src/libANGLE/renderer/metal/ContextMtl.mm @@ -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 @@ -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); @@ -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() { @@ -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)) @@ -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 &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()); + return getRenderCommandEncoder(renderTarget, Optional()); } mtl::BlitCommandEncoder *ContextMtl::getBlitCommandEncoder() @@ -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); @@ -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(); @@ -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); diff --git a/src/libANGLE/renderer/metal/FrameBufferMtl.h b/src/libANGLE/renderer/metal/FrameBufferMtl.h index d220a02ff6..70bd77d6e8 100644 --- a/src/libANGLE/renderer/metal/FrameBufferMtl.h +++ b/src/libANGLE/renderer/metal/FrameBufferMtl.h @@ -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; @@ -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(). @@ -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); @@ -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 diff --git a/src/libANGLE/renderer/metal/FrameBufferMtl.mm b/src/libANGLE/renderer/metal/FrameBufferMtl.mm index 03359bdacd..fbfe8bf364 100644 --- a/src/libANGLE/renderer/metal/FrameBufferMtl.mm +++ b/src/libANGLE/renderer/metal/FrameBufferMtl.mm @@ -45,8 +45,10 @@ } // FramebufferMtl implementation -FramebufferMtl::FramebufferMtl(const gl::FramebufferState &state, bool flipY) - : FramebufferImpl(state), mFlipY(flipY) +FramebufferMtl::FramebufferMtl(const gl::FramebufferState &state, + bool flipY, + SurfaceMtl *backbuffer) + : FramebufferImpl(state), mBackbuffer(backbuffer), mFlipY(flipY) { reset(); } @@ -159,12 +161,12 @@ GLenum FramebufferMtl::getImplementationColorReadFormat(const gl::Context *context) const { - return GetReadAttachmentInfo(context, getColorReadRenderTarget()).format; + return GetReadAttachmentInfo(context, getColorReadRenderTarget(context)).format; } GLenum FramebufferMtl::getImplementationColorReadType(const gl::Context *context) const { - return GetReadAttachmentInfo(context, getColorReadRenderTarget()).type; + return GetReadAttachmentInfo(context, getColorReadRenderTarget(context)).type; } angle::Result FramebufferMtl::readPixels(const gl::Context *context, @@ -183,7 +185,7 @@ // nothing to read return angle::Result::Continue; } - gl::Rectangle flippedArea = getReadPixelArea(clippedArea); + gl::Rectangle flippedArea = getReadPixelArea(context, clippedArea); ContextMtl *contextMtl = mtl::GetImpl(context); const gl::State &glState = context->getState(); @@ -211,7 +213,7 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse params.reverseRowOrder = !params.reverseRowOrder; } - ANGLE_TRY(readPixelsImpl(context, flippedArea, params, getColorReadRenderTarget(), + ANGLE_TRY(readPixelsImpl(context, flippedArea, params, getColorReadRenderTarget(context), static_cast(pixels) + outputSkipBytes)); return angle::Result::Continue; @@ -316,12 +318,21 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse return angle::Result::Stop; } -RenderTargetMtl *FramebufferMtl::getColorReadRenderTarget() const +RenderTargetMtl *FramebufferMtl::getColorReadRenderTarget(const gl::Context *context) const { if (mState.getReadIndex() >= mColorRenderTargets.size()) { return nullptr; } + + if (mBackbuffer) + { + if (IsError(mBackbuffer->ensureCurrentDrawableObtained(context))) + { + return nullptr; + } + } + return mColorRenderTargets[mState.getReadIndex()]; } @@ -330,9 +341,43 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse return gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height); } -const mtl::RenderPassDesc &FramebufferMtl::getRenderPassDesc(ContextMtl *context) +bool FramebufferMtl::renderPassHasStarted(ContextMtl *contextMtl) const +{ + return contextMtl->hasStartedRenderPass(mRenderPassDesc); +} + +mtl::RenderCommandEncoder *FramebufferMtl::ensureRenderPassStarted(const gl::Context *context) +{ + return ensureRenderPassStarted(context, mRenderPassDesc); +} + +mtl::RenderCommandEncoder *FramebufferMtl::ensureRenderPassStarted(const gl::Context *context, + const mtl::RenderPassDesc &desc) { - return mRenderPassDesc; + ContextMtl *contextMtl = mtl::GetImpl(context); + + if (renderPassHasStarted(contextMtl)) + { + return contextMtl->getRenderCommandEncoder(); + } + + if (mBackbuffer) + { + // Backbuffer might obtain new drawable, which means it might change the + // the native texture used as the target of the render pass. + // We need to call this before creating render encoder. + if (IsError(mBackbuffer->ensureCurrentDrawableObtained(context))) + { + return nullptr; + } + } + + // Only support ensureRenderPassStarted() with different load & store options. + // The texture, level, slice must be the same. + ASSERT(desc.equalIgnoreLoadStoreOptions(mRenderPassDesc)); + + // If this render pass already started, this will be no-op. + return contextMtl->getRenderCommandEncoder(desc); } void FramebufferMtl::onStartedDrawingToFrameBuffer(const gl::Context *context) @@ -462,13 +507,13 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse const mtl::ClearRectParams &clearOpts) { ContextMtl *contextMtl = mtl::GetImpl(context); - bool startedRenderPass = contextMtl->hasStartedRenderPass(mRenderPassDesc); + bool startedRenderPass = renderPassHasStarted(contextMtl); mtl::RenderCommandEncoder *encoder = nullptr; mtl::RenderPassDesc tempDesc = mRenderPassDesc; if (startedRenderPass) { - encoder = contextMtl->getRenderCommandEncoder(); + encoder = ensureRenderPassStarted(context); } size_t attachmentCount = 0; @@ -479,7 +524,7 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse uint32_t attachmentIdx = static_cast(attachmentCount++); mtl::RenderPassColorAttachmentDesc &colorAttachment = tempDesc.colorAttachments[attachmentIdx]; - const mtl::TextureRef &texture = colorAttachment.texture; + const mtl::TextureRef &texture = colorAttachment.texture(); if (clearColorBuffers.test(colorIndexGL)) { @@ -538,7 +583,7 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse } // Start new render encoder with loadOp=Clear - contextMtl->getRenderCommandEncoder(tempDesc); + ensureRenderPassStarted(context, tempDesc); return angle::Result::Continue; } @@ -551,7 +596,7 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse DisplayMtl *display = contextMtl->getDisplay(); // Start new render encoder if not already. - mtl::RenderCommandEncoder *encoder = contextMtl->getRenderCommandEncoder(mRenderPassDesc); + mtl::RenderCommandEncoder *encoder = ensureRenderPassStarted(context, mRenderPassDesc); display->getUtils().clearWithDraw(context, encoder, clearOpts); @@ -680,9 +725,10 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse return angle::Result::Continue; } -gl::Rectangle FramebufferMtl::getReadPixelArea(const gl::Rectangle &glArea) +gl::Rectangle FramebufferMtl::getReadPixelArea(const gl::Context *context, + const gl::Rectangle &glArea) { - RenderTargetMtl *colorReadRT = getColorReadRenderTarget(); + RenderTargetMtl *colorReadRT = getColorReadRenderTarget(context); ASSERT(colorReadRT); gl::Rectangle flippedArea = glArea; if (mFlipY) @@ -711,7 +757,7 @@ PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverse { return angle::Result::Continue; } - const mtl::TextureRef &texture = renderTarget->getTexture(); + mtl::TextureRef texture = renderTarget->getTexture(); if (!texture) { diff --git a/src/libANGLE/renderer/metal/RenderTargetMtl.h b/src/libANGLE/renderer/metal/RenderTargetMtl.h index f9ba3c3fe8..9721bb1277 100644 --- a/src/libANGLE/renderer/metal/RenderTargetMtl.h +++ b/src/libANGLE/renderer/metal/RenderTargetMtl.h @@ -32,21 +32,23 @@ class RenderTargetMtl final : public FramebufferAttachmentRenderTarget // Used in std::vector initialization. RenderTargetMtl(RenderTargetMtl &&other); - void set(const mtl::TextureRef &texture, size_t level, size_t layer, const mtl::Format &format); + void set(const mtl::TextureRef &texture, + uint32_t level, + uint32_t layer, + const mtl::Format &format); void set(const mtl::TextureRef &texture); void reset(); - const mtl::TextureRef &getTexture() const { return mTexture; } - size_t getLevelIndex() const { return mLevelIndex; } - size_t getLayerIndex() const { return mLayerIndex; } + mtl::TextureRef getTexture() const { return mTextureRenderTargetInfo->getTextureRef(); } + uint32_t getLevelIndex() const { return mTextureRenderTargetInfo->level; } + uint32_t getLayerIndex() const { return mTextureRenderTargetInfo->slice; } const mtl::Format *getFormat() const { return mFormat; } void toRenderPassAttachmentDesc(mtl::RenderPassAttachmentDesc *rpaDescOut) const; private: - mtl::TextureRef mTexture; - size_t mLevelIndex = 0; - size_t mLayerIndex = 0; + // This is shared pointer to avoid crashing when texture deleted after bound to a frame buffer. + std::shared_ptr mTextureRenderTargetInfo; const mtl::Format *mFormat = nullptr; }; } // namespace rx diff --git a/src/libANGLE/renderer/metal/RenderTargetMtl.mm b/src/libANGLE/renderer/metal/RenderTargetMtl.mm index 1ff82774de..f85b8ca6bf 100644 --- a/src/libANGLE/renderer/metal/RenderTargetMtl.mm +++ b/src/libANGLE/renderer/metal/RenderTargetMtl.mm @@ -9,9 +9,13 @@ #include "libANGLE/renderer/metal/RenderTargetMtl.h" +#include "libANGLE/renderer/metal/mtl_state_cache.h" + namespace rx { -RenderTargetMtl::RenderTargetMtl() {} +RenderTargetMtl::RenderTargetMtl() + : mTextureRenderTargetInfo(std::make_shared()) +{} RenderTargetMtl::~RenderTargetMtl() { @@ -19,39 +23,35 @@ } RenderTargetMtl::RenderTargetMtl(RenderTargetMtl &&other) - : mTexture(std::move(other.mTexture)), - mLevelIndex(other.mLevelIndex), - mLayerIndex(other.mLayerIndex) + : mTextureRenderTargetInfo(std::move(other.mTextureRenderTargetInfo)) {} void RenderTargetMtl::set(const mtl::TextureRef &texture, - size_t level, - size_t layer, + uint32_t level, + uint32_t layer, const mtl::Format &format) { - mTexture = texture; - mLevelIndex = level; - mLayerIndex = layer; - mFormat = &format; + mTextureRenderTargetInfo->texture = texture; + mTextureRenderTargetInfo->level = level; + mTextureRenderTargetInfo->slice = layer; + mFormat = &format; } void RenderTargetMtl::set(const mtl::TextureRef &texture) { - mTexture = texture; + mTextureRenderTargetInfo->texture = texture; } void RenderTargetMtl::reset() { - mTexture.reset(); - mLevelIndex = 0; - mLayerIndex = 0; - mFormat = nullptr; + mTextureRenderTargetInfo->texture.reset(); + mTextureRenderTargetInfo->level = 0; + mTextureRenderTargetInfo->slice = 0; + mFormat = nullptr; } void RenderTargetMtl::toRenderPassAttachmentDesc(mtl::RenderPassAttachmentDesc *rpaDescOut) const { - rpaDescOut->texture = mTexture; - rpaDescOut->level = static_cast(mLevelIndex); - rpaDescOut->slice = static_cast(mLayerIndex); + rpaDescOut->renderTarget = mTextureRenderTargetInfo; } } diff --git a/src/libANGLE/renderer/metal/SurfaceMtl.h b/src/libANGLE/renderer/metal/SurfaceMtl.h index abae889544..832064f9cc 100644 --- a/src/libANGLE/renderer/metal/SurfaceMtl.h +++ b/src/libANGLE/renderer/metal/SurfaceMtl.h @@ -71,14 +71,16 @@ class SurfaceMtl : public SurfaceImpl GLsizei samples, FramebufferAttachmentRenderTarget **rtOut) override; + angle::Result ensureCurrentDrawableObtained(const gl::Context *context); + private: angle::Result swapImpl(const gl::Context *context); - angle::Result ensureRenderTargetsCreated(const gl::Context *context); angle::Result obtainNextDrawable(const gl::Context *context); - angle::Result ensureDepthStencilSizeCorrect(const gl::Context *context, - gl::Framebuffer::DirtyBits *fboDirtyBits); + angle::Result ensureDepthStencilSizeCorrect(const gl::Context *context); + + CGSize calcExpectedDrawableSize() const; // Check if metal layer has been resized. - void checkIfLayerResized(); + angle::Result checkIfLayerResized(const gl::Context *context); mtl::AutoObjCObj mMetalLayer = nil; CALayer *mLayer; diff --git a/src/libANGLE/renderer/metal/SurfaceMtl.mm b/src/libANGLE/renderer/metal/SurfaceMtl.mm index fb7266cd71..9cefe26473 100644 --- a/src/libANGLE/renderer/metal/SurfaceMtl.mm +++ b/src/libANGLE/renderer/metal/SurfaceMtl.mm @@ -257,15 +257,15 @@ void StopFrameCapture() mMetalLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; #endif + // ensure drawableSize is set to correct value: + mMetalLayer.get().drawableSize = calcExpectedDrawableSize(); + if (mMetalLayer.get() != mLayer) { mMetalLayer.get().contentsScale = mLayer.contentsScale; [mLayer addSublayer:mMetalLayer.get()]; } - - // ensure drawableSize is set to correct value: - checkIfLayerResized(); } return egl::NoError(); @@ -274,23 +274,22 @@ void StopFrameCapture() FramebufferImpl *SurfaceMtl::createDefaultFramebuffer(const gl::Context *context, const gl::FramebufferState &state) { - auto fbo = new FramebufferMtl(state, /* flipY */ true); + auto fbo = new FramebufferMtl(state, /* flipY */ true, /* backbuffer */ this); return fbo; } egl::Error SurfaceMtl::makeCurrent(const gl::Context *context) { - angle::Result result = obtainNextDrawable(context); - if (result != angle::Result::Continue) - { - return egl::EglBadCurrentSurface(); - } + ContextMtl *contextMtl = mtl::GetImpl(context); + StartFrameCapture(contextMtl); + return egl::NoError(); } egl::Error SurfaceMtl::unMakeCurrent(const gl::Context *context) { + StopFrameCapture(); return egl::NoError(); } @@ -360,11 +359,6 @@ void StopFrameCapture() // width and height can change with client window resizing EGLint SurfaceMtl::getWidth() const { - if (mDrawableTexture) - { - return static_cast(mDrawableTexture->width()); - } - if (mMetalLayer) { return static_cast(mMetalLayer.get().drawableSize.width); @@ -374,11 +368,6 @@ void StopFrameCapture() EGLint SurfaceMtl::getHeight() const { - if (mDrawableTexture) - { - return static_cast(mDrawableTexture->height()); - } - if (mMetalLayer) { return static_cast(mMetalLayer.get().drawableSize.height); @@ -403,7 +392,8 @@ void StopFrameCapture() FramebufferAttachmentRenderTarget **rtOut) { // NOTE(hqle): Support MSAA. - ANGLE_TRY(ensureRenderTargetsCreated(context)); + ANGLE_TRY(ensureCurrentDrawableObtained(context)); + ANGLE_TRY(ensureDepthStencilSizeCorrect(context)); switch (binding) { @@ -425,9 +415,9 @@ void StopFrameCapture() return angle::Result::Continue; } -angle::Result SurfaceMtl::ensureRenderTargetsCreated(const gl::Context *context) +angle::Result SurfaceMtl::ensureCurrentDrawableObtained(const gl::Context *context) { - if (!mDrawableTexture) + if (!mCurrentDrawable) { ANGLE_TRY(obtainNextDrawable(context)); } @@ -435,13 +425,13 @@ void StopFrameCapture() return angle::Result::Continue; } -angle::Result SurfaceMtl::ensureDepthStencilSizeCorrect(const gl::Context *context, - gl::Framebuffer::DirtyBits *fboDirtyBits) +angle::Result SurfaceMtl::ensureDepthStencilSizeCorrect(const gl::Context *context) { - ASSERT(mDrawableTexture && mDrawableTexture->get()); + ASSERT(mMetalLayer); ContextMtl *contextMtl = mtl::GetImpl(context); - auto size = mDrawableTexture->size(); + gl::Extents size(static_cast(mMetalLayer.get().drawableSize.width), + static_cast(mMetalLayer.get().drawableSize.height), 1); if (mDepthFormat.valid() && (!mDepthTexture || mDepthTexture->size() != size)) { @@ -449,7 +439,6 @@ void StopFrameCapture() true, false, &mDepthTexture)); mDepthRenderTarget.set(mDepthTexture, 0, 0, mDepthFormat); - fboDirtyBits->set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT); } if (mStencilFormat.valid() && (!mStencilTexture || mStencilTexture->size() != size)) @@ -465,45 +454,47 @@ void StopFrameCapture() } mStencilRenderTarget.set(mStencilTexture, 0, 0, mStencilFormat); - fboDirtyBits->set(gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT); } return angle::Result::Continue; } -void SurfaceMtl::checkIfLayerResized() +CGSize SurfaceMtl::calcExpectedDrawableSize() const { - CGSize currentDrawableSize = mMetalLayer.get().drawableSize; CGSize currentLayerSize = mMetalLayer.get().bounds.size; CGFloat currentLayerContentsScale = mMetalLayer.get().contentsScale; CGSize expectedDrawableSize = CGSizeMake(currentLayerSize.width * currentLayerContentsScale, currentLayerSize.height * currentLayerContentsScale); + + return expectedDrawableSize; +} + +angle::Result SurfaceMtl::checkIfLayerResized(const gl::Context *context) +{ + CGSize currentDrawableSize = mMetalLayer.get().drawableSize; + CGSize expectedDrawableSize = calcExpectedDrawableSize(); + if (currentDrawableSize.width != expectedDrawableSize.width || currentDrawableSize.height != expectedDrawableSize.height) { // Resize the internal drawable texture. mMetalLayer.get().drawableSize = expectedDrawableSize; } + + // Now we have to resize depth stencil buffers if required. + ANGLE_TRY(ensureDepthStencilSizeCorrect(context)); + + return angle::Result::Continue; } angle::Result SurfaceMtl::obtainNextDrawable(const gl::Context *context) { - checkIfLayerResized(); - ANGLE_MTL_OBJC_SCOPE { ContextMtl *contextMtl = mtl::GetImpl(context); - StartFrameCapture(contextMtl); - ANGLE_MTL_TRY(contextMtl, mMetalLayer); - if (mDrawableTexture) - { - mDrawableTexture->set(nil); - } - - mCurrentDrawable = nil; mCurrentDrawable.retainAssign([mMetalLayer nextDrawable]); if (!mCurrentDrawable) { @@ -528,38 +519,30 @@ void StopFrameCapture() ANGLE_MTL_LOG("Current metal drawable size=%d,%d", mDrawableTexture->width(), mDrawableTexture->height()); - gl::Framebuffer::DirtyBits fboDirtyBits; - fboDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); - - // Now we have to resize depth stencil buffers if necessary. - ANGLE_TRY(ensureDepthStencilSizeCorrect(context, &fboDirtyBits)); - - // Need to notify default framebuffer to invalidate its render targets. - // Since a new drawable texture has been obtained, also, the depth stencil - // buffers might have been resized. - gl::Framebuffer *defaultFbo = - context->getFramebuffer(gl::Framebuffer::kDefaultDrawFramebufferHandle); - if (defaultFbo) - { - FramebufferMtl *framebufferMtl = mtl::GetImpl(defaultFbo); - ANGLE_TRY(framebufferMtl->syncState(context, fboDirtyBits)); - } - return angle::Result::Continue; } } angle::Result SurfaceMtl::swapImpl(const gl::Context *context) { - ANGLE_TRY(ensureRenderTargetsCreated(context)); + if (mCurrentDrawable) + { + ASSERT(mDrawableTexture); - ContextMtl *contextMtl = mtl::GetImpl(context); + ContextMtl *contextMtl = mtl::GetImpl(context); - contextMtl->present(context, mCurrentDrawable); + contextMtl->present(context, mCurrentDrawable); - StopFrameCapture(); + StopFrameCapture(); + StartFrameCapture(contextMtl); + + // Invalidate current drawable + mDrawableTexture->set(nil); + mCurrentDrawable = nil; + } - ANGLE_TRY(obtainNextDrawable(context)); + // Check if layer was resized + ANGLE_TRY(checkIfLayerResized(context)); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/metal/TextureMtl.h b/src/libANGLE/renderer/metal/TextureMtl.h index 6070ece8bb..cb91ec3ade 100644 --- a/src/libANGLE/renderer/metal/TextureMtl.h +++ b/src/libANGLE/renderer/metal/TextureMtl.h @@ -225,19 +225,18 @@ class TextureMtl : public TextureImpl angle::Result generateMipmapCPU(const gl::Context *context); - using ImagesMipChain = std::map; - mtl::Format mFormat; // The real texture used by Metal draw calls. mtl::TextureRef mNativeTexture; id mMetalSamplerState = nil; - std::vector mLayeredRenderTargets; + // Full mipmap views of texture at each slice/cube face: std::vector mLayeredTextureViews; // Stored images array defined by glTexImage/glCopy*. // Once the images array is complete, they will be transferred to real texture object. - std::map mTexImages; + std::map> mTexImages; + std::map> mTexImageRenderTargets; bool mIsPow2 = false; }; diff --git a/src/libANGLE/renderer/metal/TextureMtl.mm b/src/libANGLE/renderer/metal/TextureMtl.mm index ddcf41f284..0f5819fb74 100644 --- a/src/libANGLE/renderer/metal/TextureMtl.mm +++ b/src/libANGLE/renderer/metal/TextureMtl.mm @@ -337,14 +337,17 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) mNativeTexture = nullptr; mMetalSamplerState = nil; - for (RenderTargetMtl &rt : mLayeredRenderTargets) - { - rt.set(nullptr); - } - if (releaseImages) { mTexImages.clear(); + // Clear render target cache for each texture's image + for (auto &sliceRenderTargets : mTexImageRenderTargets) + { + for (auto &mipRenderTarget : sliceRenderTargets.second) + { + mipRenderTarget.set(nullptr); + } + } } mLayeredTextureViews.clear(); @@ -375,8 +378,6 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) ANGLE_TRY(mtl::Texture::Make2DTexture(contextMtl, mFormat, desc.size.width, desc.size.height, mips, false, true, &mNativeTexture)); - mLayeredRenderTargets.resize(1); - mLayeredRenderTargets[0].set(mNativeTexture, 0, 0, mFormat); mLayeredTextureViews.resize(1); mLayeredTextureViews[0] = mNativeTexture; break; @@ -384,12 +385,10 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) layers = 6; ANGLE_TRY(mtl::Texture::MakeCubeTexture(contextMtl, mFormat, desc.size.width, mips, false, true, &mNativeTexture)); - mLayeredRenderTargets.resize(gl::kCubeFaceCount); mLayeredTextureViews.resize(gl::kCubeFaceCount); for (uint32_t f = 0; f < gl::kCubeFaceCount; ++f) { mLayeredTextureViews[f] = mNativeTexture->createCubeFaceView(f); - mLayeredRenderTargets[f].set(mLayeredTextureViews[f], 0, 0, mFormat); } break; default: @@ -399,13 +398,12 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) ANGLE_TRY(checkForEmulatedChannels(context, mFormat, mNativeTexture)); // Transfer data from images to actual texture object - mtl::BlitCommandEncoder *encoder = nullptr; - std::map &imagesToTransfer = mTexImages; + mtl::BlitCommandEncoder *encoder = nullptr; for (int layer = 0; layer < layers; ++layer) { for (GLuint mip = 0; mip < mips; ++mip) { - mtl::TextureRef &imageToTransfer = imagesToTransfer[layer][mip]; + mtl::TextureRef &imageToTransfer = mTexImages[layer][mip]; // Only transfer if this mip & slice image has been defined and in correct size & // format. @@ -430,6 +428,8 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) // So that in future, glTexSubImage* will update the actual texture // directly. mTexImages[layer][mip] = mNativeTexture->createSliceMipView(layer, mip); + + mTexImageRenderTargets[layer][mip].set(mTexImages[layer][mip], 0, 0, mFormat); } } @@ -802,10 +802,10 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) switch (imageIndex.getType()) { case gl::TextureType::_2D: - *rtOut = &mLayeredRenderTargets[0]; + *rtOut = &mTexImageRenderTargets[0][0]; break; case gl::TextureType::CubeMap: - *rtOut = &mLayeredRenderTargets[imageIndex.cubeMapFaceIndex()]; + *rtOut = &mTexImageRenderTargets[imageIndex.cubeMapFaceIndex()][0]; break; default: UNREACHABLE(); @@ -915,6 +915,8 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) // Cache last defined image format: mFormat = mtlFormat; mtl::TextureRef &image = mTexImages[GetImageLayerIndex(index)][index.getLevelIndex()]; + RenderTargetMtl &imageRtt = + mTexImageRenderTargets[GetImageLayerIndex(index)][index.getLevelIndex()]; // If actual texture exists, it means the size hasn't been changed, no need to create new image if (mNativeTexture && image) @@ -935,6 +937,8 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) default: UNREACHABLE(); } + + imageRtt.set(image, 0, 0, mtlFormat); } // Make sure emulated channels are properly initialized @@ -1192,7 +1196,7 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) DisplayMtl *displayMtl = contextMtl->getDisplay(); FramebufferMtl *framebufferMtl = mtl::GetImpl(source); - RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(); + RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(context); if (!colorReadRT || !colorReadRT->getTexture()) { @@ -1201,10 +1205,11 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) } mtl::TextureRef &image = mTexImages[GetImageLayerIndex(index)][index.getLevelIndex()]; + const RenderTargetMtl &imageRtt = + mTexImageRenderTargets[GetImageLayerIndex(index)][index.getLevelIndex()]; ASSERT(image && image->valid()); - mtl::RenderCommandEncoder *cmdEncoder = - contextMtl->getRenderCommandEncoder(image, GetImageBaseLevelIndex(image)); + mtl::RenderCommandEncoder *cmdEncoder = contextMtl->getRenderCommandEncoder(imageRtt); mtl::BlitParams blitParams; blitParams.dstOffset = modifiedDestOffset; @@ -1233,7 +1238,7 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) ContextMtl *contextMtl = mtl::GetImpl(context); FramebufferMtl *framebufferMtl = mtl::GetImpl(source); - RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(); + RenderTargetMtl *colorReadRT = framebufferMtl->getColorReadRenderTarget(context); if (!colorReadRT || !colorReadRT->getTexture()) { @@ -1257,9 +1262,9 @@ GLuint GetImageLayerIndex(const gl::ImageIndex &index) PackPixelsParams packParams(srcRowArea, dstFormat, dstRowPitch, false, nullptr, 0); // Read pixels from framebuffer to memory: - gl::Rectangle flippedSrcRowArea = framebufferMtl->getReadPixelArea(srcRowArea); + gl::Rectangle flippedSrcRowArea = framebufferMtl->getReadPixelArea(context, srcRowArea); ANGLE_TRY(framebufferMtl->readPixelsImpl(context, flippedSrcRowArea, packParams, - framebufferMtl->getColorReadRenderTarget(), + framebufferMtl->getColorReadRenderTarget(context), conversionRow.data())); // Upload to texture diff --git a/src/libANGLE/renderer/metal/mtl_command_buffer.mm b/src/libANGLE/renderer/metal/mtl_command_buffer.mm index d6f27b56b1..6777359b6f 100644 --- a/src/libANGLE/renderer/metal/mtl_command_buffer.mm +++ b/src/libANGLE/renderer/metal/mtl_command_buffer.mm @@ -501,16 +501,16 @@ // mask writing dependency for (uint32_t i = 0; i < mRenderPassDesc.numColorAttachments; ++i) { - initWriteDependencyAndStoreAction(mRenderPassDesc.colorAttachments[i].texture, + initWriteDependencyAndStoreAction(mRenderPassDesc.colorAttachments[i].texture(), &mRenderPassDesc.colorAttachments[i].storeAction); mColorInitialStoreActions[i] = mRenderPassDesc.colorAttachments[i].storeAction; } - initWriteDependencyAndStoreAction(mRenderPassDesc.depthAttachment.texture, + initWriteDependencyAndStoreAction(mRenderPassDesc.depthAttachment.texture(), &mRenderPassDesc.depthAttachment.storeAction); mDepthInitialStoreAction = mRenderPassDesc.depthAttachment.storeAction; - initWriteDependencyAndStoreAction(mRenderPassDesc.stencilAttachment.texture, + initWriteDependencyAndStoreAction(mRenderPassDesc.stencilAttachment.texture(), &mRenderPassDesc.stencilAttachment.storeAction); mStencilInitialStoreAction = mRenderPassDesc.stencilAttachment.storeAction; diff --git a/src/libANGLE/renderer/metal/mtl_render_utils.mm b/src/libANGLE/renderer/metal/mtl_render_utils.mm index 49c030e0dc..8c6c42dc79 100644 --- a/src/libANGLE/renderer/metal/mtl_render_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_render_utils.mm @@ -243,11 +243,11 @@ void GetFirstLastIndicesFromClientElements(GLsizei count, { overridedParams.clearColor.reset(); } - if (!renderPassDesc.depthAttachment.texture) + if (!renderPassDesc.depthAttachment.texture()) { overridedParams.clearDepth.reset(); } - if (!renderPassDesc.stencilAttachment.texture) + if (!renderPassDesc.stencilAttachment.texture()) { overridedParams.clearStencil.reset(); } @@ -312,23 +312,23 @@ void GetFirstLastIndicesFromClientElements(GLsizei count, { renderPassAttachment = renderPassDesc.colorAttachments[0]; } - else if (renderPassDesc.depthAttachment.texture) + else if (renderPassDesc.depthAttachment.texture()) { renderPassAttachment = renderPassDesc.depthAttachment; } else { - ASSERT(renderPassDesc.stencilAttachment.texture); + ASSERT(renderPassDesc.stencilAttachment.texture()); renderPassAttachment = renderPassDesc.stencilAttachment; } - auto texture = renderPassAttachment.texture; + auto texture = renderPassAttachment.texture(); viewport = - GetViewport(params.clearArea, texture->height(renderPassAttachment.level), params.flipY); + GetViewport(params.clearArea, texture->height(renderPassAttachment.level()), params.flipY); - scissorRect = - GetScissorRect(params.clearArea, texture->height(renderPassAttachment.level), params.flipY); + scissorRect = GetScissorRect(params.clearArea, texture->height(renderPassAttachment.level()), + params.flipY); cmdEncoder->setViewport(viewport); cmdEncoder->setScissorRect(scissorRect); @@ -363,14 +363,14 @@ void GetFirstLastIndicesFromClientElements(GLsizei count, const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc(); const RenderPassColorAttachmentDesc &renderPassColorAttachment = renderPassDesc.colorAttachments[0]; - auto texture = renderPassColorAttachment.texture; + auto texture = renderPassColorAttachment.texture(); gl::Rectangle dstRect(params.dstOffset.x, params.dstOffset.y, params.srcRect.width, params.srcRect.height); MTLViewport viewportMtl = - GetViewport(dstRect, texture->height(renderPassColorAttachment.level), params.dstFlipY); - MTLScissorRect scissorRectMtl = - GetScissorRect(dstRect, texture->height(renderPassColorAttachment.level), params.dstFlipY); + GetViewport(dstRect, texture->height(renderPassColorAttachment.level()), params.dstFlipY); + MTLScissorRect scissorRectMtl = GetScissorRect( + dstRect, texture->height(renderPassColorAttachment.level()), params.dstFlipY); cmdEncoder->setViewport(viewportMtl); cmdEncoder->setScissorRect(scissorRectMtl); diff --git a/src/libANGLE/renderer/metal/mtl_state_cache.h b/src/libANGLE/renderer/metal/mtl_state_cache.h index bc0f0a4482..261e66747f 100644 --- a/src/libANGLE/renderer/metal/mtl_state_cache.h +++ b/src/libANGLE/renderer/metal/mtl_state_cache.h @@ -233,6 +233,15 @@ struct RenderPipelineDesc bool rasterizationEnabled; }; +struct RenderPassAttachmentTextureTargetDesc +{ + TextureRef getTextureRef() const { return texture.lock(); } + + TextureWeakRef texture; + uint32_t level = 0; + uint32_t slice = 0; +}; + struct RenderPassAttachmentDesc { RenderPassAttachmentDesc(); @@ -242,9 +251,15 @@ struct RenderPassAttachmentDesc bool equalIgnoreLoadStoreOptions(const RenderPassAttachmentDesc &other) const; bool operator==(const RenderPassAttachmentDesc &other) const; - TextureRef texture; - uint32_t level; - uint32_t slice; + ANGLE_INLINE TextureRef texture() const + { + return renderTarget ? renderTarget->getTextureRef() : nullptr; + } + ANGLE_INLINE uint32_t level() const { return renderTarget ? renderTarget->level : 0; } + ANGLE_INLINE uint32_t slice() const { return renderTarget ? renderTarget->slice : 0; } + + // This is shared pointer to avoid crashing when texture deleted after bound to a frame buffer. + std::shared_ptr renderTarget; MTLLoadAction loadAction; MTLStoreAction storeAction; MTLStoreActionOptions storeActionOptions; diff --git a/src/libANGLE/renderer/metal/mtl_state_cache.mm b/src/libANGLE/renderer/metal/mtl_state_cache.mm index 91003c3b25..1359f84abc 100644 --- a/src/libANGLE/renderer/metal/mtl_state_cache.mm +++ b/src/libANGLE/renderer/metal/mtl_state_cache.mm @@ -172,9 +172,9 @@ inline T ToObjC(const T p) void ToObjC(MTLRenderPassAttachmentDescriptor *dst, const RenderPassAttachmentDesc &src) { - ANGLE_OBJC_CP_PROPERTY(dst, src, texture); - ANGLE_OBJC_CP_PROPERTY(dst, src, level); - ANGLE_OBJC_CP_PROPERTY(dst, src, slice); + dst.texture = ToObjC(src.texture()); + dst.level = src.level(); + dst.slice = src.slice(); ANGLE_OBJC_CP_PROPERTY(dst, src, loadAction); ANGLE_OBJC_CP_PROPERTY(dst, src, storeAction); @@ -633,9 +633,7 @@ void ToObjC(MTLRenderPassAttachmentDescriptor *dst, const RenderPassAttachmentDe void RenderPassAttachmentDesc::reset() { - texture.reset(); - level = 0; - slice = 0; + renderTarget = nullptr; loadAction = MTLLoadActionLoad; storeAction = MTLStoreActionStore; storeActionOptions = MTLStoreActionOptionNone; @@ -644,7 +642,8 @@ void ToObjC(MTLRenderPassAttachmentDescriptor *dst, const RenderPassAttachmentDe bool RenderPassAttachmentDesc::equalIgnoreLoadStoreOptions( const RenderPassAttachmentDesc &other) const { - return texture == other.texture && level == other.level && slice == other.slice; + return renderTarget == other.renderTarget || + (texture() == other.texture() && level() == other.level() && slice() == other.slice()); } bool RenderPassAttachmentDesc::operator==(const RenderPassAttachmentDesc &other) const @@ -681,7 +680,7 @@ void ToObjC(MTLRenderPassAttachmentDescriptor *dst, const RenderPassAttachmentDe for (uint32_t i = 0; i < this->numColorAttachments; ++i) { auto &renderPassColorAttachment = this->colorAttachments[i]; - auto texture = renderPassColorAttachment.texture; + auto texture = renderPassColorAttachment.texture(); // Copy parameters from blend state outputDescriptor.colorAttachments[i].update(blendState); @@ -702,11 +701,11 @@ void ToObjC(MTLRenderPassAttachmentDescriptor *dst, const RenderPassAttachmentDe } } - auto depthTexture = this->depthAttachment.texture; + auto depthTexture = this->depthAttachment.texture(); outputDescriptor.depthAttachmentPixelFormat = depthTexture ? depthTexture->pixelFormat() : MTLPixelFormatInvalid; - auto stencilTexture = this->stencilAttachment.texture; + auto stencilTexture = this->stencilAttachment.texture(); outputDescriptor.stencilAttachmentPixelFormat = stencilTexture ? stencilTexture->pixelFormat() : MTLPixelFormatInvalid; }