1*8975f5c5SAndroid Build Coastguard Worker// 2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2019 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker// 6*8975f5c5SAndroid Build Coastguard Worker// FramebufferMtl.mm: 7*8975f5c5SAndroid Build Coastguard Worker// Implements the class methods for FramebufferMtl. 8*8975f5c5SAndroid Build Coastguard Worker// 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/angletypes.h" 11*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h" 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Worker#include <TargetConditionals.h> 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Worker#include "common/MemoryBuffer.h" 16*8975f5c5SAndroid Build Coastguard Worker#include "common/angleutils.h" 17*8975f5c5SAndroid Build Coastguard Worker#include "common/debug.h" 18*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/ErrorStrings.h" 19*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/BufferMtl.h" 20*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/DisplayMtl.h" 21*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/FrameBufferMtl.h" 22*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/SurfaceMtl.h" 23*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_utils.h" 24*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/renderer_utils.h" 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard Workernamespace rx 27*8975f5c5SAndroid Build Coastguard Worker{ 28*8975f5c5SAndroid Build Coastguard Workernamespace 29*8975f5c5SAndroid Build Coastguard Worker{ 30*8975f5c5SAndroid Build Coastguard Worker// Override clear color based on texture's write mask 31*8975f5c5SAndroid Build Coastguard Workervoid OverrideMTLClearColor(const mtl::TextureRef &texture, 32*8975f5c5SAndroid Build Coastguard Worker const mtl::ClearColorValue &clearColor, 33*8975f5c5SAndroid Build Coastguard Worker MTLClearColor *colorOut) 34*8975f5c5SAndroid Build Coastguard Worker{ 35*8975f5c5SAndroid Build Coastguard Worker if (texture) 36*8975f5c5SAndroid Build Coastguard Worker { 37*8975f5c5SAndroid Build Coastguard Worker *colorOut = mtl::EmulatedAlphaClearColor(clearColor.toMTLClearColor(), 38*8975f5c5SAndroid Build Coastguard Worker texture->getColorWritableMask()); 39*8975f5c5SAndroid Build Coastguard Worker } 40*8975f5c5SAndroid Build Coastguard Worker else 41*8975f5c5SAndroid Build Coastguard Worker { 42*8975f5c5SAndroid Build Coastguard Worker *colorOut = clearColor.toMTLClearColor(); 43*8975f5c5SAndroid Build Coastguard Worker } 44*8975f5c5SAndroid Build Coastguard Worker} 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Workerconst gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context, 47*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *renderTarget) 48*8975f5c5SAndroid Build Coastguard Worker{ 49*8975f5c5SAndroid Build Coastguard Worker GLenum implFormat; 50*8975f5c5SAndroid Build Coastguard Worker 51*8975f5c5SAndroid Build Coastguard Worker if (renderTarget) 52*8975f5c5SAndroid Build Coastguard Worker { 53*8975f5c5SAndroid Build Coastguard Worker implFormat = renderTarget->getFormat().actualAngleFormat().fboImplementationInternalFormat; 54*8975f5c5SAndroid Build Coastguard Worker } 55*8975f5c5SAndroid Build Coastguard Worker else 56*8975f5c5SAndroid Build Coastguard Worker { 57*8975f5c5SAndroid Build Coastguard Worker implFormat = GL_NONE; 58*8975f5c5SAndroid Build Coastguard Worker } 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker return gl::GetSizedInternalFormatInfo(implFormat); 61*8975f5c5SAndroid Build Coastguard Worker} 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Workerangle::Result CopyTextureSliceLevelToTempBuffer(const gl::Context *context, 64*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &srcTexture, 65*8975f5c5SAndroid Build Coastguard Worker const mtl::MipmapNativeLevel &mipNativeLevel, 66*8975f5c5SAndroid Build Coastguard Worker uint32_t layerIndex, 67*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef *outBuffer) 68*8975f5c5SAndroid Build Coastguard Worker{ 69*8975f5c5SAndroid Build Coastguard Worker ASSERT(outBuffer); 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 72*8975f5c5SAndroid Build Coastguard Worker auto formatId = mtl::Format::MetalToAngleFormatID(srcTexture->pixelFormat()); 73*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &metalFormat = contextMtl->getPixelFormat(formatId); 74*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = metalFormat.actualAngleFormat(); 75*8975f5c5SAndroid Build Coastguard Worker 76*8975f5c5SAndroid Build Coastguard Worker uint32_t width = srcTexture->width(mipNativeLevel); 77*8975f5c5SAndroid Build Coastguard Worker uint32_t height = srcTexture->height(mipNativeLevel); 78*8975f5c5SAndroid Build Coastguard Worker uint32_t sizeInBytes = width * height * angleFormat.pixelBytes; 79*8975f5c5SAndroid Build Coastguard Worker 80*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef tempBuffer; 81*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::Buffer::MakeBufferWithStorageMode( 82*8975f5c5SAndroid Build Coastguard Worker contextMtl, mtl::Buffer::getStorageModeForSharedBuffer(contextMtl), sizeInBytes, nullptr, 83*8975f5c5SAndroid Build Coastguard Worker &tempBuffer)); 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle region(0, 0, width, height); 86*8975f5c5SAndroid Build Coastguard Worker uint32_t bytesPerRow = angleFormat.pixelBytes * width; 87*8975f5c5SAndroid Build Coastguard Worker uint32_t destOffset = 0; 88*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::ReadTexturePerSliceBytesToBuffer(context, srcTexture, bytesPerRow, region, 89*8975f5c5SAndroid Build Coastguard Worker mipNativeLevel, layerIndex, destOffset, 90*8975f5c5SAndroid Build Coastguard Worker tempBuffer)); 91*8975f5c5SAndroid Build Coastguard Worker 92*8975f5c5SAndroid Build Coastguard Worker *outBuffer = tempBuffer; 93*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 94*8975f5c5SAndroid Build Coastguard Worker} 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Workerangle::Result Copy2DTextureSlice0Level0ToTempTexture(const gl::Context *context, 97*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &srcTexture, 98*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef *outTexture) 99*8975f5c5SAndroid Build Coastguard Worker{ 100*8975f5c5SAndroid Build Coastguard Worker ASSERT(outTexture); 101*8975f5c5SAndroid Build Coastguard Worker 102*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 103*8975f5c5SAndroid Build Coastguard Worker auto formatId = mtl::Format::MetalToAngleFormatID(srcTexture->pixelFormat()); 104*8975f5c5SAndroid Build Coastguard Worker const auto &format = contextMtl->getPixelFormat(formatId); 105*8975f5c5SAndroid Build Coastguard Worker 106*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef tempTexture; 107*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::Texture::Make2DTexture(contextMtl, format, srcTexture->widthAt0(), 108*8975f5c5SAndroid Build Coastguard Worker srcTexture->heightAt0(), srcTexture->mipmapLevels(), 109*8975f5c5SAndroid Build Coastguard Worker false, true, &tempTexture)); 110*8975f5c5SAndroid Build Coastguard Worker 111*8975f5c5SAndroid Build Coastguard Worker auto *blitEncoder = contextMtl->getBlitCommandEncoder(); 112*8975f5c5SAndroid Build Coastguard Worker blitEncoder->copyTexture(srcTexture, 113*8975f5c5SAndroid Build Coastguard Worker 0, // srcStartSlice 114*8975f5c5SAndroid Build Coastguard Worker mtl::MipmapNativeLevel(0), // MipmapNativeLevel 115*8975f5c5SAndroid Build Coastguard Worker tempTexture, // dst 116*8975f5c5SAndroid Build Coastguard Worker 0, // dstStartSlice 117*8975f5c5SAndroid Build Coastguard Worker mtl::MipmapNativeLevel(0), // dstStartLevel 118*8975f5c5SAndroid Build Coastguard Worker 1, // sliceCount, 119*8975f5c5SAndroid Build Coastguard Worker 1); // levelCount 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker *outTexture = tempTexture; 122*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 123*8975f5c5SAndroid Build Coastguard Worker} 124*8975f5c5SAndroid Build Coastguard Worker 125*8975f5c5SAndroid Build Coastguard Worker} // namespace 126*8975f5c5SAndroid Build Coastguard Worker 127*8975f5c5SAndroid Build Coastguard Worker// FramebufferMtl implementation 128*8975f5c5SAndroid Build Coastguard WorkerFramebufferMtl::FramebufferMtl(const gl::FramebufferState &state, ContextMtl *context, bool flipY) 129*8975f5c5SAndroid Build Coastguard Worker : FramebufferImpl(state), 130*8975f5c5SAndroid Build Coastguard Worker mColorRenderTargets(context->getNativeCaps().maxColorAttachments, nullptr), 131*8975f5c5SAndroid Build Coastguard Worker mBackbuffer(nullptr), 132*8975f5c5SAndroid Build Coastguard Worker mFlipY(flipY) 133*8975f5c5SAndroid Build Coastguard Worker{ 134*8975f5c5SAndroid Build Coastguard Worker reset(); 135*8975f5c5SAndroid Build Coastguard Worker} 136*8975f5c5SAndroid Build Coastguard Worker 137*8975f5c5SAndroid Build Coastguard WorkerFramebufferMtl::~FramebufferMtl() {} 138*8975f5c5SAndroid Build Coastguard Worker 139*8975f5c5SAndroid Build Coastguard Workervoid FramebufferMtl::reset() 140*8975f5c5SAndroid Build Coastguard Worker{ 141*8975f5c5SAndroid Build Coastguard Worker for (auto &rt : mColorRenderTargets) 142*8975f5c5SAndroid Build Coastguard Worker { 143*8975f5c5SAndroid Build Coastguard Worker rt = nullptr; 144*8975f5c5SAndroid Build Coastguard Worker } 145*8975f5c5SAndroid Build Coastguard Worker mDepthRenderTarget = mStencilRenderTarget = nullptr; 146*8975f5c5SAndroid Build Coastguard Worker 147*8975f5c5SAndroid Build Coastguard Worker mRenderPassFirstColorAttachmentFormat = nullptr; 148*8975f5c5SAndroid Build Coastguard Worker 149*8975f5c5SAndroid Build Coastguard Worker mReadPixelBuffer = nullptr; 150*8975f5c5SAndroid Build Coastguard Worker} 151*8975f5c5SAndroid Build Coastguard Worker 152*8975f5c5SAndroid Build Coastguard Workervoid FramebufferMtl::destroy(const gl::Context *context) 153*8975f5c5SAndroid Build Coastguard Worker{ 154*8975f5c5SAndroid Build Coastguard Worker reset(); 155*8975f5c5SAndroid Build Coastguard Worker} 156*8975f5c5SAndroid Build Coastguard Worker 157*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::discard(const gl::Context *context, 158*8975f5c5SAndroid Build Coastguard Worker size_t count, 159*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments) 160*8975f5c5SAndroid Build Coastguard Worker{ 161*8975f5c5SAndroid Build Coastguard Worker return invalidate(context, count, attachments); 162*8975f5c5SAndroid Build Coastguard Worker} 163*8975f5c5SAndroid Build Coastguard Worker 164*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::invalidate(const gl::Context *context, 165*8975f5c5SAndroid Build Coastguard Worker size_t count, 166*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments) 167*8975f5c5SAndroid Build Coastguard Worker{ 168*8975f5c5SAndroid Build Coastguard Worker return invalidateImpl(context, count, attachments); 169*8975f5c5SAndroid Build Coastguard Worker} 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::invalidateSub(const gl::Context *context, 172*8975f5c5SAndroid Build Coastguard Worker size_t count, 173*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments, 174*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area) 175*8975f5c5SAndroid Build Coastguard Worker{ 176*8975f5c5SAndroid Build Coastguard Worker if (area.encloses(getCompleteRenderArea())) 177*8975f5c5SAndroid Build Coastguard Worker { 178*8975f5c5SAndroid Build Coastguard Worker return invalidateImpl(context, count, attachments); 179*8975f5c5SAndroid Build Coastguard Worker } 180*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 181*8975f5c5SAndroid Build Coastguard Worker} 182*8975f5c5SAndroid Build Coastguard Worker 183*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clear(const gl::Context *context, GLbitfield mask) 184*8975f5c5SAndroid Build Coastguard Worker{ 185*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 186*8975f5c5SAndroid Build Coastguard Worker 187*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(contextMtl->getForceResyncDrawFramebuffer())) 188*8975f5c5SAndroid Build Coastguard Worker { 189*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 190*8975f5c5SAndroid Build Coastguard Worker gl::Command::Clear)); 191*8975f5c5SAndroid Build Coastguard Worker } 192*8975f5c5SAndroid Build Coastguard Worker 193*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams clearOpts; 194*8975f5c5SAndroid Build Coastguard Worker 195*8975f5c5SAndroid Build Coastguard Worker bool clearColor = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT)); 196*8975f5c5SAndroid Build Coastguard Worker bool clearDepth = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT)); 197*8975f5c5SAndroid Build Coastguard Worker bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT)); 198*8975f5c5SAndroid Build Coastguard Worker 199*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers; 200*8975f5c5SAndroid Build Coastguard Worker if (clearColor) 201*8975f5c5SAndroid Build Coastguard Worker { 202*8975f5c5SAndroid Build Coastguard Worker clearColorBuffers = mState.getEnabledDrawBuffers(); 203*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearColor = contextMtl->getClearColorValue(); 204*8975f5c5SAndroid Build Coastguard Worker } 205*8975f5c5SAndroid Build Coastguard Worker if (clearDepth) 206*8975f5c5SAndroid Build Coastguard Worker { 207*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearDepth = contextMtl->getClearDepthValue(); 208*8975f5c5SAndroid Build Coastguard Worker } 209*8975f5c5SAndroid Build Coastguard Worker if (clearStencil) 210*8975f5c5SAndroid Build Coastguard Worker { 211*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearStencil = contextMtl->getClearStencilValue(); 212*8975f5c5SAndroid Build Coastguard Worker } 213*8975f5c5SAndroid Build Coastguard Worker 214*8975f5c5SAndroid Build Coastguard Worker return clearImpl(context, clearColorBuffers, &clearOpts); 215*8975f5c5SAndroid Build Coastguard Worker} 216*8975f5c5SAndroid Build Coastguard Worker 217*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearBufferfv(const gl::Context *context, 218*8975f5c5SAndroid Build Coastguard Worker GLenum buffer, 219*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer, 220*8975f5c5SAndroid Build Coastguard Worker const GLfloat *values) 221*8975f5c5SAndroid Build Coastguard Worker{ 222*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mtl::GetImpl(context)->getForceResyncDrawFramebuffer())) 223*8975f5c5SAndroid Build Coastguard Worker { 224*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 225*8975f5c5SAndroid Build Coastguard Worker gl::Command::Clear)); 226*8975f5c5SAndroid Build Coastguard Worker } 227*8975f5c5SAndroid Build Coastguard Worker 228*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams clearOpts; 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers; 231*8975f5c5SAndroid Build Coastguard Worker if (buffer == GL_DEPTH) 232*8975f5c5SAndroid Build Coastguard Worker { 233*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearDepth = values[0]; 234*8975f5c5SAndroid Build Coastguard Worker } 235*8975f5c5SAndroid Build Coastguard Worker else 236*8975f5c5SAndroid Build Coastguard Worker { 237*8975f5c5SAndroid Build Coastguard Worker clearColorBuffers.set(drawbuffer); 238*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearColor = mtl::ClearColorValue(values[0], values[1], values[2], values[3]); 239*8975f5c5SAndroid Build Coastguard Worker } 240*8975f5c5SAndroid Build Coastguard Worker 241*8975f5c5SAndroid Build Coastguard Worker return clearImpl(context, clearColorBuffers, &clearOpts); 242*8975f5c5SAndroid Build Coastguard Worker} 243*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearBufferuiv(const gl::Context *context, 244*8975f5c5SAndroid Build Coastguard Worker GLenum buffer, 245*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer, 246*8975f5c5SAndroid Build Coastguard Worker const GLuint *values) 247*8975f5c5SAndroid Build Coastguard Worker{ 248*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mtl::GetImpl(context)->getForceResyncDrawFramebuffer())) 249*8975f5c5SAndroid Build Coastguard Worker { 250*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 251*8975f5c5SAndroid Build Coastguard Worker gl::Command::Clear)); 252*8975f5c5SAndroid Build Coastguard Worker } 253*8975f5c5SAndroid Build Coastguard Worker 254*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers; 255*8975f5c5SAndroid Build Coastguard Worker clearColorBuffers.set(drawbuffer); 256*8975f5c5SAndroid Build Coastguard Worker 257*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams clearOpts; 258*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearColor = mtl::ClearColorValue(values[0], values[1], values[2], values[3]); 259*8975f5c5SAndroid Build Coastguard Worker 260*8975f5c5SAndroid Build Coastguard Worker return clearImpl(context, clearColorBuffers, &clearOpts); 261*8975f5c5SAndroid Build Coastguard Worker} 262*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearBufferiv(const gl::Context *context, 263*8975f5c5SAndroid Build Coastguard Worker GLenum buffer, 264*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer, 265*8975f5c5SAndroid Build Coastguard Worker const GLint *values) 266*8975f5c5SAndroid Build Coastguard Worker{ 267*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mtl::GetImpl(context)->getForceResyncDrawFramebuffer())) 268*8975f5c5SAndroid Build Coastguard Worker { 269*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 270*8975f5c5SAndroid Build Coastguard Worker gl::Command::Clear)); 271*8975f5c5SAndroid Build Coastguard Worker } 272*8975f5c5SAndroid Build Coastguard Worker 273*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams clearOpts; 274*8975f5c5SAndroid Build Coastguard Worker 275*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers; 276*8975f5c5SAndroid Build Coastguard Worker if (buffer == GL_STENCIL) 277*8975f5c5SAndroid Build Coastguard Worker { 278*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearStencil = values[0] & mtl::kStencilMaskAll; 279*8975f5c5SAndroid Build Coastguard Worker } 280*8975f5c5SAndroid Build Coastguard Worker else 281*8975f5c5SAndroid Build Coastguard Worker { 282*8975f5c5SAndroid Build Coastguard Worker clearColorBuffers.set(drawbuffer); 283*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearColor = mtl::ClearColorValue(values[0], values[1], values[2], values[3]); 284*8975f5c5SAndroid Build Coastguard Worker } 285*8975f5c5SAndroid Build Coastguard Worker 286*8975f5c5SAndroid Build Coastguard Worker return clearImpl(context, clearColorBuffers, &clearOpts); 287*8975f5c5SAndroid Build Coastguard Worker} 288*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearBufferfi(const gl::Context *context, 289*8975f5c5SAndroid Build Coastguard Worker GLenum buffer, 290*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer, 291*8975f5c5SAndroid Build Coastguard Worker GLfloat depth, 292*8975f5c5SAndroid Build Coastguard Worker GLint stencil) 293*8975f5c5SAndroid Build Coastguard Worker{ 294*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams clearOpts; 295*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearDepth = depth; 296*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearStencil = stencil & mtl::kStencilMaskAll; 297*8975f5c5SAndroid Build Coastguard Worker 298*8975f5c5SAndroid Build Coastguard Worker return clearImpl(context, gl::DrawBufferMask(), &clearOpts); 299*8975f5c5SAndroid Build Coastguard Worker} 300*8975f5c5SAndroid Build Coastguard Worker 301*8975f5c5SAndroid Build Coastguard Workerconst gl::InternalFormat &FramebufferMtl::getImplementationColorReadFormat( 302*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context) const 303*8975f5c5SAndroid Build Coastguard Worker{ 304*8975f5c5SAndroid Build Coastguard Worker return GetReadAttachmentInfo(context, getColorReadRenderTargetNoCache(context)); 305*8975f5c5SAndroid Build Coastguard Worker} 306*8975f5c5SAndroid Build Coastguard Worker 307*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::readPixels(const gl::Context *context, 308*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area, 309*8975f5c5SAndroid Build Coastguard Worker GLenum format, 310*8975f5c5SAndroid Build Coastguard Worker GLenum type, 311*8975f5c5SAndroid Build Coastguard Worker const gl::PixelPackState &pack, 312*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *packBuffer, 313*8975f5c5SAndroid Build Coastguard Worker void *pixels) 314*8975f5c5SAndroid Build Coastguard Worker{ 315*8975f5c5SAndroid Build Coastguard Worker // Clip read area to framebuffer. 316*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &fbSize = getState().getReadAttachment()->getSize(); 317*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height); 318*8975f5c5SAndroid Build Coastguard Worker 319*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle clippedArea; 320*8975f5c5SAndroid Build Coastguard Worker if (!ClipRectangle(area, fbRect, &clippedArea)) 321*8975f5c5SAndroid Build Coastguard Worker { 322*8975f5c5SAndroid Build Coastguard Worker // nothing to read 323*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 324*8975f5c5SAndroid Build Coastguard Worker } 325*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle flippedArea = getCorrectFlippedReadArea(context, clippedArea); 326*8975f5c5SAndroid Build Coastguard Worker 327*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 328*8975f5c5SAndroid Build Coastguard Worker 329*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type); 330*8975f5c5SAndroid Build Coastguard Worker 331*8975f5c5SAndroid Build Coastguard Worker GLuint outputPitch = 0; 332*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_MATH(contextMtl, 333*8975f5c5SAndroid Build Coastguard Worker sizedFormatInfo.computeRowPitch(type, area.width, pack.alignment, 334*8975f5c5SAndroid Build Coastguard Worker pack.rowLength, &outputPitch)); 335*8975f5c5SAndroid Build Coastguard Worker GLuint outputSkipBytes = 0; 336*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_MATH(contextMtl, sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, pack, 337*8975f5c5SAndroid Build Coastguard Worker false, &outputSkipBytes)); 338*8975f5c5SAndroid Build Coastguard Worker 339*8975f5c5SAndroid Build Coastguard Worker outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes + 340*8975f5c5SAndroid Build Coastguard Worker (clippedArea.y - area.y) * outputPitch; 341*8975f5c5SAndroid Build Coastguard Worker 342*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = GetFormatFromFormatType(format, type); 343*8975f5c5SAndroid Build Coastguard Worker 344*8975f5c5SAndroid Build Coastguard Worker PackPixelsParams params(flippedArea, angleFormat, outputPitch, pack.reverseRowOrder, packBuffer, 345*8975f5c5SAndroid Build Coastguard Worker 0); 346*8975f5c5SAndroid Build Coastguard Worker 347*8975f5c5SAndroid Build Coastguard Worker if (params.packBuffer) 348*8975f5c5SAndroid Build Coastguard Worker { 349*8975f5c5SAndroid Build Coastguard Worker // If PBO is active, pixels is treated as offset. 350*8975f5c5SAndroid Build Coastguard Worker params.offset = reinterpret_cast<ptrdiff_t>(pixels) + outputSkipBytes; 351*8975f5c5SAndroid Build Coastguard Worker } 352*8975f5c5SAndroid Build Coastguard Worker 353*8975f5c5SAndroid Build Coastguard Worker if (mFlipY) 354*8975f5c5SAndroid Build Coastguard Worker { 355*8975f5c5SAndroid Build Coastguard Worker params.reverseRowOrder = !params.reverseRowOrder; 356*8975f5c5SAndroid Build Coastguard Worker } 357*8975f5c5SAndroid Build Coastguard Worker 358*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(readPixelsImpl(context, flippedArea, params, getColorReadRenderTarget(context), 359*8975f5c5SAndroid Build Coastguard Worker static_cast<uint8_t *>(pixels) + outputSkipBytes)); 360*8975f5c5SAndroid Build Coastguard Worker 361*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 362*8975f5c5SAndroid Build Coastguard Worker} 363*8975f5c5SAndroid Build Coastguard Worker 364*8975f5c5SAndroid Build Coastguard Workernamespace 365*8975f5c5SAndroid Build Coastguard Worker{ 366*8975f5c5SAndroid Build Coastguard Worker 367*8975f5c5SAndroid Build Coastguard Workerusing FloatRectangle = gl::RectangleImpl<float>; 368*8975f5c5SAndroid Build Coastguard Worker 369*8975f5c5SAndroid Build Coastguard Workerfloat clamp0Max(float v, float max) 370*8975f5c5SAndroid Build Coastguard Worker{ 371*8975f5c5SAndroid Build Coastguard Worker return std::max(0.0f, std::min(max, v)); 372*8975f5c5SAndroid Build Coastguard Worker} 373*8975f5c5SAndroid Build Coastguard Worker 374*8975f5c5SAndroid Build Coastguard Workervoid ClampToBoundsAndAdjustCorrespondingValue(float a, 375*8975f5c5SAndroid Build Coastguard Worker float originalASize, 376*8975f5c5SAndroid Build Coastguard Worker float maxSize, 377*8975f5c5SAndroid Build Coastguard Worker float b, 378*8975f5c5SAndroid Build Coastguard Worker float originalBSize, 379*8975f5c5SAndroid Build Coastguard Worker float *newA, 380*8975f5c5SAndroid Build Coastguard Worker float *newB) 381*8975f5c5SAndroid Build Coastguard Worker{ 382*8975f5c5SAndroid Build Coastguard Worker float clippedA = clamp0Max(a, maxSize); 383*8975f5c5SAndroid Build Coastguard Worker float delta = clippedA - a; 384*8975f5c5SAndroid Build Coastguard Worker *newA = clippedA; 385*8975f5c5SAndroid Build Coastguard Worker *newB = b + delta * originalBSize / originalASize; 386*8975f5c5SAndroid Build Coastguard Worker} 387*8975f5c5SAndroid Build Coastguard Worker 388*8975f5c5SAndroid Build Coastguard Workervoid ClipRectToBoundsAndAdjustCorrespondingRect(const FloatRectangle &a, 389*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalA, 390*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &clipDimensions, 391*8975f5c5SAndroid Build Coastguard Worker const FloatRectangle &b, 392*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalB, 393*8975f5c5SAndroid Build Coastguard Worker FloatRectangle *newA, 394*8975f5c5SAndroid Build Coastguard Worker FloatRectangle *newB) 395*8975f5c5SAndroid Build Coastguard Worker{ 396*8975f5c5SAndroid Build Coastguard Worker float newAValues[4]; 397*8975f5c5SAndroid Build Coastguard Worker float newBValues[4]; 398*8975f5c5SAndroid Build Coastguard Worker ClampToBoundsAndAdjustCorrespondingValue(a.x0(), originalA.width, clipDimensions.width, b.x0(), 399*8975f5c5SAndroid Build Coastguard Worker originalB.width, &newAValues[0], &newBValues[0]); 400*8975f5c5SAndroid Build Coastguard Worker ClampToBoundsAndAdjustCorrespondingValue(a.y0(), originalA.height, clipDimensions.height, 401*8975f5c5SAndroid Build Coastguard Worker b.y0(), originalB.height, &newAValues[1], 402*8975f5c5SAndroid Build Coastguard Worker &newBValues[1]); 403*8975f5c5SAndroid Build Coastguard Worker ClampToBoundsAndAdjustCorrespondingValue(a.x1(), originalA.width, clipDimensions.width, b.x1(), 404*8975f5c5SAndroid Build Coastguard Worker originalB.width, &newAValues[2], &newBValues[2]); 405*8975f5c5SAndroid Build Coastguard Worker ClampToBoundsAndAdjustCorrespondingValue(a.y1(), originalA.height, clipDimensions.height, 406*8975f5c5SAndroid Build Coastguard Worker b.y1(), originalB.height, &newAValues[3], 407*8975f5c5SAndroid Build Coastguard Worker &newBValues[3]); 408*8975f5c5SAndroid Build Coastguard Worker 409*8975f5c5SAndroid Build Coastguard Worker *newA = FloatRectangle(newAValues); 410*8975f5c5SAndroid Build Coastguard Worker *newB = FloatRectangle(newBValues); 411*8975f5c5SAndroid Build Coastguard Worker} 412*8975f5c5SAndroid Build Coastguard Worker 413*8975f5c5SAndroid Build Coastguard Workervoid ClipRectsToBoundsAndAdjustCorrespondingRect(const FloatRectangle &a, 414*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalA, 415*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &aClipDimensions, 416*8975f5c5SAndroid Build Coastguard Worker const FloatRectangle &b, 417*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalB, 418*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &bClipDimensions, 419*8975f5c5SAndroid Build Coastguard Worker FloatRectangle *newA, 420*8975f5c5SAndroid Build Coastguard Worker FloatRectangle *newB) 421*8975f5c5SAndroid Build Coastguard Worker{ 422*8975f5c5SAndroid Build Coastguard Worker FloatRectangle tempA; 423*8975f5c5SAndroid Build Coastguard Worker FloatRectangle tempB; 424*8975f5c5SAndroid Build Coastguard Worker ClipRectToBoundsAndAdjustCorrespondingRect(a, originalA, aClipDimensions, b, originalB, &tempA, 425*8975f5c5SAndroid Build Coastguard Worker &tempB); 426*8975f5c5SAndroid Build Coastguard Worker ClipRectToBoundsAndAdjustCorrespondingRect(tempB, originalB, bClipDimensions, tempA, originalA, 427*8975f5c5SAndroid Build Coastguard Worker newB, newA); 428*8975f5c5SAndroid Build Coastguard Worker} 429*8975f5c5SAndroid Build Coastguard Worker 430*8975f5c5SAndroid Build Coastguard Workervoid RoundValueAndAdjustCorrespondingValue(float a, 431*8975f5c5SAndroid Build Coastguard Worker float originalASize, 432*8975f5c5SAndroid Build Coastguard Worker float b, 433*8975f5c5SAndroid Build Coastguard Worker float originalBSize, 434*8975f5c5SAndroid Build Coastguard Worker int *newA, 435*8975f5c5SAndroid Build Coastguard Worker float *newB) 436*8975f5c5SAndroid Build Coastguard Worker{ 437*8975f5c5SAndroid Build Coastguard Worker float roundedA = std::round(a); 438*8975f5c5SAndroid Build Coastguard Worker float delta = roundedA - a; 439*8975f5c5SAndroid Build Coastguard Worker *newA = static_cast<int>(roundedA); 440*8975f5c5SAndroid Build Coastguard Worker *newB = b + delta * originalBSize / originalASize; 441*8975f5c5SAndroid Build Coastguard Worker} 442*8975f5c5SAndroid Build Coastguard Worker 443*8975f5c5SAndroid Build Coastguard Workergl::Rectangle RoundRectToPixelsAndAdjustCorrespondingRectToMatch(const FloatRectangle &a, 444*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalA, 445*8975f5c5SAndroid Build Coastguard Worker const FloatRectangle &b, 446*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &originalB, 447*8975f5c5SAndroid Build Coastguard Worker FloatRectangle *newB) 448*8975f5c5SAndroid Build Coastguard Worker{ 449*8975f5c5SAndroid Build Coastguard Worker int newAValues[4]; 450*8975f5c5SAndroid Build Coastguard Worker float newBValues[4]; 451*8975f5c5SAndroid Build Coastguard Worker RoundValueAndAdjustCorrespondingValue(a.x0(), originalA.width, b.x0(), originalB.width, 452*8975f5c5SAndroid Build Coastguard Worker &newAValues[0], &newBValues[0]); 453*8975f5c5SAndroid Build Coastguard Worker RoundValueAndAdjustCorrespondingValue(a.y0(), originalA.height, b.y0(), originalB.height, 454*8975f5c5SAndroid Build Coastguard Worker &newAValues[1], &newBValues[1]); 455*8975f5c5SAndroid Build Coastguard Worker RoundValueAndAdjustCorrespondingValue(a.x1(), originalA.width, b.x1(), originalB.width, 456*8975f5c5SAndroid Build Coastguard Worker &newAValues[2], &newBValues[2]); 457*8975f5c5SAndroid Build Coastguard Worker RoundValueAndAdjustCorrespondingValue(a.y1(), originalA.height, b.y1(), originalB.height, 458*8975f5c5SAndroid Build Coastguard Worker &newAValues[3], &newBValues[3]); 459*8975f5c5SAndroid Build Coastguard Worker 460*8975f5c5SAndroid Build Coastguard Worker *newB = FloatRectangle(newBValues); 461*8975f5c5SAndroid Build Coastguard Worker return gl::Rectangle(newAValues[0], newAValues[1], newAValues[2] - newAValues[0], 462*8975f5c5SAndroid Build Coastguard Worker newAValues[3] - newAValues[1]); 463*8975f5c5SAndroid Build Coastguard Worker} 464*8975f5c5SAndroid Build Coastguard Worker 465*8975f5c5SAndroid Build Coastguard Worker} // namespace 466*8975f5c5SAndroid Build Coastguard Worker 467*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::blit(const gl::Context *context, 468*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceAreaIn, 469*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &destAreaIn, 470*8975f5c5SAndroid Build Coastguard Worker GLbitfield mask, 471*8975f5c5SAndroid Build Coastguard Worker GLenum filter) 472*8975f5c5SAndroid Build Coastguard Worker{ 473*8975f5c5SAndroid Build Coastguard Worker bool blitColorBuffer = (mask & GL_COLOR_BUFFER_BIT) != 0; 474*8975f5c5SAndroid Build Coastguard Worker bool blitDepthBuffer = (mask & GL_DEPTH_BUFFER_BIT) != 0; 475*8975f5c5SAndroid Build Coastguard Worker bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0; 476*8975f5c5SAndroid Build Coastguard Worker 477*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = context->getState(); 478*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *glSrcFramebuffer = glState.getReadFramebuffer(); 479*8975f5c5SAndroid Build Coastguard Worker 480*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *srcFrameBuffer = mtl::GetImpl(glSrcFramebuffer); 481*8975f5c5SAndroid Build Coastguard Worker 482*8975f5c5SAndroid Build Coastguard Worker blitColorBuffer = 483*8975f5c5SAndroid Build Coastguard Worker blitColorBuffer && srcFrameBuffer->getColorReadRenderTarget(context) != nullptr; 484*8975f5c5SAndroid Build Coastguard Worker blitDepthBuffer = blitDepthBuffer && srcFrameBuffer->getDepthRenderTarget() != nullptr; 485*8975f5c5SAndroid Build Coastguard Worker blitStencilBuffer = blitStencilBuffer && srcFrameBuffer->getStencilRenderTarget() != nullptr; 486*8975f5c5SAndroid Build Coastguard Worker 487*8975f5c5SAndroid Build Coastguard Worker if (!blitColorBuffer && !blitDepthBuffer && !blitStencilBuffer) 488*8975f5c5SAndroid Build Coastguard Worker { 489*8975f5c5SAndroid Build Coastguard Worker // No-op 490*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 491*8975f5c5SAndroid Build Coastguard Worker } 492*8975f5c5SAndroid Build Coastguard Worker 493*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mtl::GetImpl(context)->getForceResyncDrawFramebuffer())) 494*8975f5c5SAndroid Build Coastguard Worker { 495*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 496*8975f5c5SAndroid Build Coastguard Worker gl::Command::Blit)); 497*8975f5c5SAndroid Build Coastguard Worker } 498*8975f5c5SAndroid Build Coastguard Worker 499*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle srcFramebufferDimensions = srcFrameBuffer->getCompleteRenderArea(); 500*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle dstFramebufferDimensions = this->getCompleteRenderArea(); 501*8975f5c5SAndroid Build Coastguard Worker 502*8975f5c5SAndroid Build Coastguard Worker FloatRectangle srcRect(sourceAreaIn); 503*8975f5c5SAndroid Build Coastguard Worker FloatRectangle dstRect(destAreaIn); 504*8975f5c5SAndroid Build Coastguard Worker 505*8975f5c5SAndroid Build Coastguard Worker FloatRectangle clippedSrcRect; 506*8975f5c5SAndroid Build Coastguard Worker FloatRectangle clippedDstRect; 507*8975f5c5SAndroid Build Coastguard Worker ClipRectsToBoundsAndAdjustCorrespondingRect(srcRect, sourceAreaIn, srcFramebufferDimensions, 508*8975f5c5SAndroid Build Coastguard Worker dstRect, destAreaIn, dstFramebufferDimensions, 509*8975f5c5SAndroid Build Coastguard Worker &clippedSrcRect, &clippedDstRect); 510*8975f5c5SAndroid Build Coastguard Worker 511*8975f5c5SAndroid Build Coastguard Worker FloatRectangle adjustedSrcRect; 512*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle srcClippedDestArea = RoundRectToPixelsAndAdjustCorrespondingRectToMatch( 513*8975f5c5SAndroid Build Coastguard Worker clippedDstRect, destAreaIn, clippedSrcRect, sourceAreaIn, &adjustedSrcRect); 514*8975f5c5SAndroid Build Coastguard Worker 515*8975f5c5SAndroid Build Coastguard Worker if (srcFrameBuffer->flipY()) 516*8975f5c5SAndroid Build Coastguard Worker { 517*8975f5c5SAndroid Build Coastguard Worker adjustedSrcRect.y = 518*8975f5c5SAndroid Build Coastguard Worker srcFramebufferDimensions.height - adjustedSrcRect.y - adjustedSrcRect.height; 519*8975f5c5SAndroid Build Coastguard Worker adjustedSrcRect = adjustedSrcRect.flip(false, true); 520*8975f5c5SAndroid Build Coastguard Worker } 521*8975f5c5SAndroid Build Coastguard Worker 522*8975f5c5SAndroid Build Coastguard Worker // If the destination is flipped in either direction, we will flip the source instead so that 523*8975f5c5SAndroid Build Coastguard Worker // the destination area is always unflipped. 524*8975f5c5SAndroid Build Coastguard Worker adjustedSrcRect = 525*8975f5c5SAndroid Build Coastguard Worker adjustedSrcRect.flip(srcClippedDestArea.isReversedX(), srcClippedDestArea.isReversedY()); 526*8975f5c5SAndroid Build Coastguard Worker srcClippedDestArea = srcClippedDestArea.removeReversal(); 527*8975f5c5SAndroid Build Coastguard Worker 528*8975f5c5SAndroid Build Coastguard Worker // Clip the destination area to the framebuffer size and scissor. 529*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle scissoredDestArea; 530*8975f5c5SAndroid Build Coastguard Worker if (!gl::ClipRectangle(ClipRectToScissor(glState, dstFramebufferDimensions, false), 531*8975f5c5SAndroid Build Coastguard Worker srcClippedDestArea, &scissoredDestArea)) 532*8975f5c5SAndroid Build Coastguard Worker { 533*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 534*8975f5c5SAndroid Build Coastguard Worker } 535*8975f5c5SAndroid Build Coastguard Worker 536*8975f5c5SAndroid Build Coastguard Worker // Use blit with draw 537*8975f5c5SAndroid Build Coastguard Worker mtl::BlitParams baseParams; 538*8975f5c5SAndroid Build Coastguard Worker baseParams.dstTextureSize = 539*8975f5c5SAndroid Build Coastguard Worker gl::Extents(dstFramebufferDimensions.width, dstFramebufferDimensions.height, 1); 540*8975f5c5SAndroid Build Coastguard Worker baseParams.dstRect = srcClippedDestArea; 541*8975f5c5SAndroid Build Coastguard Worker baseParams.dstScissorRect = scissoredDestArea; 542*8975f5c5SAndroid Build Coastguard Worker baseParams.dstFlipY = this->flipY(); 543*8975f5c5SAndroid Build Coastguard Worker 544*8975f5c5SAndroid Build Coastguard Worker baseParams.srcNormalizedCoords = 545*8975f5c5SAndroid Build Coastguard Worker mtl::NormalizedCoords(adjustedSrcRect.x, adjustedSrcRect.y, adjustedSrcRect.width, 546*8975f5c5SAndroid Build Coastguard Worker adjustedSrcRect.height, srcFramebufferDimensions); 547*8975f5c5SAndroid Build Coastguard Worker // This flag is for auto flipping the rect inside RenderUtils. Since we already flip it using 548*8975f5c5SAndroid Build Coastguard Worker // getCorrectFlippedReadArea(). This flag is not needed. 549*8975f5c5SAndroid Build Coastguard Worker baseParams.srcYFlipped = false; 550*8975f5c5SAndroid Build Coastguard Worker baseParams.unpackFlipX = false; 551*8975f5c5SAndroid Build Coastguard Worker baseParams.unpackFlipY = false; 552*8975f5c5SAndroid Build Coastguard Worker 553*8975f5c5SAndroid Build Coastguard Worker return blitWithDraw(context, srcFrameBuffer, blitColorBuffer, blitDepthBuffer, 554*8975f5c5SAndroid Build Coastguard Worker blitStencilBuffer, filter, baseParams); 555*8975f5c5SAndroid Build Coastguard Worker} 556*8975f5c5SAndroid Build Coastguard Worker 557*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::blitWithDraw(const gl::Context *context, 558*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *srcFrameBuffer, 559*8975f5c5SAndroid Build Coastguard Worker bool blitColorBuffer, 560*8975f5c5SAndroid Build Coastguard Worker bool blitDepthBuffer, 561*8975f5c5SAndroid Build Coastguard Worker bool blitStencilBuffer, 562*8975f5c5SAndroid Build Coastguard Worker GLenum filter, 563*8975f5c5SAndroid Build Coastguard Worker const mtl::BlitParams &baseParams) 564*8975f5c5SAndroid Build Coastguard Worker{ 565*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 566*8975f5c5SAndroid Build Coastguard Worker // Use blit with draw 567*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *renderEncoder = nullptr; 568*8975f5c5SAndroid Build Coastguard Worker 569*8975f5c5SAndroid Build Coastguard Worker // Blit Depth & stencil 570*8975f5c5SAndroid Build Coastguard Worker if (blitDepthBuffer || blitStencilBuffer) 571*8975f5c5SAndroid Build Coastguard Worker { 572*8975f5c5SAndroid Build Coastguard Worker mtl::DepthStencilBlitParams dsBlitParams; 573*8975f5c5SAndroid Build Coastguard Worker memcpy(&dsBlitParams, &baseParams, sizeof(baseParams)); 574*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *srcDepthRt = srcFrameBuffer->getDepthRenderTarget(); 575*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *srcStencilRt = srcFrameBuffer->getStencilRenderTarget(); 576*8975f5c5SAndroid Build Coastguard Worker 577*8975f5c5SAndroid Build Coastguard Worker if (blitDepthBuffer) 578*8975f5c5SAndroid Build Coastguard Worker { 579*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.src = srcDepthRt->getTexture(); 580*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLevel = srcDepthRt->getLevelIndex(); 581*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLayer = srcDepthRt->getLayerIndex(); 582*8975f5c5SAndroid Build Coastguard Worker } 583*8975f5c5SAndroid Build Coastguard Worker 584*8975f5c5SAndroid Build Coastguard Worker if (blitStencilBuffer && srcStencilRt->getTexture()) 585*8975f5c5SAndroid Build Coastguard Worker { 586*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcStencil = srcStencilRt->getTexture()->getStencilView(); 587*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLevel = srcStencilRt->getLevelIndex(); 588*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLayer = srcStencilRt->getLayerIndex(); 589*8975f5c5SAndroid Build Coastguard Worker 590*8975f5c5SAndroid Build Coastguard Worker if (!contextMtl->getDisplay()->getFeatures().hasShaderStencilOutput.enabled && 591*8975f5c5SAndroid Build Coastguard Worker mStencilRenderTarget) 592*8975f5c5SAndroid Build Coastguard Worker { 593*8975f5c5SAndroid Build Coastguard Worker // Directly writing to stencil in shader is not supported, use temporary copy buffer 594*8975f5c5SAndroid Build Coastguard Worker // work around. This is a compute pass. 595*8975f5c5SAndroid Build Coastguard Worker mtl::StencilBlitViaBufferParams stencilOnlyBlitParams = dsBlitParams; 596*8975f5c5SAndroid Build Coastguard Worker stencilOnlyBlitParams.dstStencil = mStencilRenderTarget->getTexture(); 597*8975f5c5SAndroid Build Coastguard Worker stencilOnlyBlitParams.dstStencilLayer = mStencilRenderTarget->getLayerIndex(); 598*8975f5c5SAndroid Build Coastguard Worker stencilOnlyBlitParams.dstStencilLevel = mStencilRenderTarget->getLevelIndex(); 599*8975f5c5SAndroid Build Coastguard Worker stencilOnlyBlitParams.dstPackedDepthStencilFormat = 600*8975f5c5SAndroid Build Coastguard Worker mStencilRenderTarget->getFormat().hasDepthAndStencilBits(); 601*8975f5c5SAndroid Build Coastguard Worker 602*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitStencilViaCopyBuffer( 603*8975f5c5SAndroid Build Coastguard Worker context, stencilOnlyBlitParams)); 604*8975f5c5SAndroid Build Coastguard Worker 605*8975f5c5SAndroid Build Coastguard Worker // Prevent the stencil to be blitted with draw again 606*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcStencil = nullptr; 607*8975f5c5SAndroid Build Coastguard Worker } 608*8975f5c5SAndroid Build Coastguard Worker } 609*8975f5c5SAndroid Build Coastguard Worker 610*8975f5c5SAndroid Build Coastguard Worker // The actual blitting of depth and/or stencil 611*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderPassStarted(context, &renderEncoder)); 612*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitDepthStencilWithDraw( 613*8975f5c5SAndroid Build Coastguard Worker context, renderEncoder, dsBlitParams)); 614*8975f5c5SAndroid Build Coastguard Worker } // if (blitDepthBuffer || blitStencilBuffer) 615*8975f5c5SAndroid Build Coastguard Worker else 616*8975f5c5SAndroid Build Coastguard Worker { 617*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderPassStarted(context, &renderEncoder)); 618*8975f5c5SAndroid Build Coastguard Worker } 619*8975f5c5SAndroid Build Coastguard Worker 620*8975f5c5SAndroid Build Coastguard Worker // Blit color 621*8975f5c5SAndroid Build Coastguard Worker if (blitColorBuffer) 622*8975f5c5SAndroid Build Coastguard Worker { 623*8975f5c5SAndroid Build Coastguard Worker mtl::ColorBlitParams colorBlitParams; 624*8975f5c5SAndroid Build Coastguard Worker memcpy(&colorBlitParams, &baseParams, sizeof(baseParams)); 625*8975f5c5SAndroid Build Coastguard Worker 626*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *srcColorRt = srcFrameBuffer->getColorReadRenderTarget(context); 627*8975f5c5SAndroid Build Coastguard Worker ASSERT(srcColorRt); 628*8975f5c5SAndroid Build Coastguard Worker 629*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.src = srcColorRt->getTexture(); 630*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.srcLevel = srcColorRt->getLevelIndex(); 631*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.srcLayer = srcColorRt->getLayerIndex(); 632*8975f5c5SAndroid Build Coastguard Worker 633*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.enabledBuffers = getState().getEnabledDrawBuffers(); 634*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.filter = filter; 635*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.dstLuminance = srcColorRt->getFormat().actualAngleFormat().isLUMA(); 636*8975f5c5SAndroid Build Coastguard Worker 637*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitColorWithDraw( 638*8975f5c5SAndroid Build Coastguard Worker context, renderEncoder, srcColorRt->getFormat().actualAngleFormat(), colorBlitParams)); 639*8975f5c5SAndroid Build Coastguard Worker } 640*8975f5c5SAndroid Build Coastguard Worker 641*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 642*8975f5c5SAndroid Build Coastguard Worker} 643*8975f5c5SAndroid Build Coastguard Worker 644*8975f5c5SAndroid Build Coastguard Workerbool FramebufferMtl::totalBitsUsedIsLessThanOrEqualToMaxBitsSupported( 645*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context) const 646*8975f5c5SAndroid Build Coastguard Worker{ 647*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 648*8975f5c5SAndroid Build Coastguard Worker 649*8975f5c5SAndroid Build Coastguard Worker uint32_t bitsUsed = 0; 650*8975f5c5SAndroid Build Coastguard Worker for (const gl::FramebufferAttachment &attachment : mState.getColorAttachments()) 651*8975f5c5SAndroid Build Coastguard Worker { 652*8975f5c5SAndroid Build Coastguard Worker if (attachment.isAttached()) 653*8975f5c5SAndroid Build Coastguard Worker { 654*8975f5c5SAndroid Build Coastguard Worker bitsUsed += attachment.getRedSize() + attachment.getGreenSize() + 655*8975f5c5SAndroid Build Coastguard Worker attachment.getBlueSize() + attachment.getAlphaSize(); 656*8975f5c5SAndroid Build Coastguard Worker } 657*8975f5c5SAndroid Build Coastguard Worker } 658*8975f5c5SAndroid Build Coastguard Worker 659*8975f5c5SAndroid Build Coastguard Worker return bitsUsed <= contextMtl->getDisplay()->getMaxColorTargetBits(); 660*8975f5c5SAndroid Build Coastguard Worker} 661*8975f5c5SAndroid Build Coastguard Worker 662*8975f5c5SAndroid Build Coastguard Workergl::FramebufferStatus FramebufferMtl::checkStatus(const gl::Context *context) const 663*8975f5c5SAndroid Build Coastguard Worker{ 664*8975f5c5SAndroid Build Coastguard Worker if (mState.hasSeparateDepthAndStencilAttachments()) 665*8975f5c5SAndroid Build Coastguard Worker { 666*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 667*8975f5c5SAndroid Build Coastguard Worker if (!contextMtl->getDisplay()->getFeatures().allowSeparateDepthStencilBuffers.enabled) 668*8975f5c5SAndroid Build Coastguard Worker { 669*8975f5c5SAndroid Build Coastguard Worker return gl::FramebufferStatus::Incomplete( 670*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED, 671*8975f5c5SAndroid Build Coastguard Worker gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers); 672*8975f5c5SAndroid Build Coastguard Worker } 673*8975f5c5SAndroid Build Coastguard Worker 674*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getDepthAttachment()->getFormat().info->depthBits > 0); 675*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getStencilAttachment()->getFormat().info->stencilBits > 0); 676*8975f5c5SAndroid Build Coastguard Worker if (mState.getDepthAttachment()->getFormat().info->stencilBits != 0 || 677*8975f5c5SAndroid Build Coastguard Worker mState.getStencilAttachment()->getFormat().info->depthBits != 0) 678*8975f5c5SAndroid Build Coastguard Worker { 679*8975f5c5SAndroid Build Coastguard Worker return gl::FramebufferStatus::Incomplete( 680*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED, 681*8975f5c5SAndroid Build Coastguard Worker gl::err:: 682*8975f5c5SAndroid Build Coastguard Worker kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffersCombinedFormat); 683*8975f5c5SAndroid Build Coastguard Worker } 684*8975f5c5SAndroid Build Coastguard Worker } 685*8975f5c5SAndroid Build Coastguard Worker 686*8975f5c5SAndroid Build Coastguard Worker if (!totalBitsUsedIsLessThanOrEqualToMaxBitsSupported(context)) 687*8975f5c5SAndroid Build Coastguard Worker { 688*8975f5c5SAndroid Build Coastguard Worker return gl::FramebufferStatus::Incomplete( 689*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED, 690*8975f5c5SAndroid Build Coastguard Worker gl::err::kFramebufferIncompleteColorBitsUsedExceedsMaxColorBitsSupported); 691*8975f5c5SAndroid Build Coastguard Worker } 692*8975f5c5SAndroid Build Coastguard Worker 693*8975f5c5SAndroid Build Coastguard Worker return gl::FramebufferStatus::Complete(); 694*8975f5c5SAndroid Build Coastguard Worker} 695*8975f5c5SAndroid Build Coastguard Worker 696*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::syncState(const gl::Context *context, 697*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 698*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer::DirtyBits &dirtyBits, 699*8975f5c5SAndroid Build Coastguard Worker gl::Command command) 700*8975f5c5SAndroid Build Coastguard Worker{ 701*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 702*8975f5c5SAndroid Build Coastguard Worker bool mustNotifyContext = false; 703*8975f5c5SAndroid Build Coastguard Worker // Cache old mRenderPassDesc before update*RenderTarget() invalidate it. 704*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc oldRenderPassDesc = mRenderPassDesc; 705*8975f5c5SAndroid Build Coastguard Worker 706*8975f5c5SAndroid Build Coastguard Worker for (size_t dirtyBit : dirtyBits) 707*8975f5c5SAndroid Build Coastguard Worker { 708*8975f5c5SAndroid Build Coastguard Worker switch (dirtyBit) 709*8975f5c5SAndroid Build Coastguard Worker { 710*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: 711*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(updateDepthRenderTarget(context)); 712*8975f5c5SAndroid Build Coastguard Worker break; 713*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: 714*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(updateStencilRenderTarget(context)); 715*8975f5c5SAndroid Build Coastguard Worker break; 716*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS: 717*8975f5c5SAndroid Build Coastguard Worker // Restore depth attachment load action as its content may have been updated 718*8975f5c5SAndroid Build Coastguard Worker // after framebuffer invalidation. 719*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.depthAttachment.loadAction = MTLLoadActionLoad; 720*8975f5c5SAndroid Build Coastguard Worker break; 721*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS: 722*8975f5c5SAndroid Build Coastguard Worker // Restore stencil attachment load action as its content may have been updated 723*8975f5c5SAndroid Build Coastguard Worker // after framebuffer invalidation. 724*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.stencilAttachment.loadAction = MTLLoadActionLoad; 725*8975f5c5SAndroid Build Coastguard Worker break; 726*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS: 727*8975f5c5SAndroid Build Coastguard Worker mustNotifyContext = true; 728*8975f5c5SAndroid Build Coastguard Worker break; 729*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_READ_BUFFER: 730*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH: 731*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT: 732*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES: 733*8975f5c5SAndroid Build Coastguard Worker case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS: 734*8975f5c5SAndroid Build Coastguard Worker break; 735*8975f5c5SAndroid Build Coastguard Worker default: 736*8975f5c5SAndroid Build Coastguard Worker { 737*8975f5c5SAndroid Build Coastguard Worker static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits"); 738*8975f5c5SAndroid Build Coastguard Worker if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) 739*8975f5c5SAndroid Build Coastguard Worker { 740*8975f5c5SAndroid Build Coastguard Worker size_t colorIndexGL = static_cast<size_t>( 741*8975f5c5SAndroid Build Coastguard Worker dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); 742*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(updateColorRenderTarget(context, colorIndexGL)); 743*8975f5c5SAndroid Build Coastguard Worker } 744*8975f5c5SAndroid Build Coastguard Worker else 745*8975f5c5SAndroid Build Coastguard Worker { 746*8975f5c5SAndroid Build Coastguard Worker ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 && 747*8975f5c5SAndroid Build Coastguard Worker dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX); 748*8975f5c5SAndroid Build Coastguard Worker // NOTE: might need to notify context. 749*8975f5c5SAndroid Build Coastguard Worker 750*8975f5c5SAndroid Build Coastguard Worker // Restore color attachment load action as its content may have been updated 751*8975f5c5SAndroid Build Coastguard Worker // after framebuffer invalidation. 752*8975f5c5SAndroid Build Coastguard Worker size_t colorIndexGL = static_cast<size_t>( 753*8975f5c5SAndroid Build Coastguard Worker dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0); 754*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.colorAttachments[colorIndexGL].loadAction = MTLLoadActionLoad; 755*8975f5c5SAndroid Build Coastguard Worker } 756*8975f5c5SAndroid Build Coastguard Worker break; 757*8975f5c5SAndroid Build Coastguard Worker } 758*8975f5c5SAndroid Build Coastguard Worker } 759*8975f5c5SAndroid Build Coastguard Worker } 760*8975f5c5SAndroid Build Coastguard Worker 761*8975f5c5SAndroid Build Coastguard Worker // If attachments have been changed and this is the current draw framebuffer, 762*8975f5c5SAndroid Build Coastguard Worker // update the Metal context's incompatible attachments cache before preparing a render pass. 763*8975f5c5SAndroid Build Coastguard Worker static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits"); 764*8975f5c5SAndroid Build Coastguard Worker constexpr gl::Framebuffer::DirtyBits kAttachmentsMask = 765*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer::DirtyBits::Mask(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX); 766*8975f5c5SAndroid Build Coastguard Worker if (mustNotifyContext || (dirtyBits & kAttachmentsMask).any()) 767*8975f5c5SAndroid Build Coastguard Worker { 768*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = context->getState(); 769*8975f5c5SAndroid Build Coastguard Worker if (mtl::GetImpl(glState.getDrawFramebuffer()) == this) 770*8975f5c5SAndroid Build Coastguard Worker { 771*8975f5c5SAndroid Build Coastguard Worker contextMtl->updateIncompatibleAttachments(glState); 772*8975f5c5SAndroid Build Coastguard Worker } 773*8975f5c5SAndroid Build Coastguard Worker } 774*8975f5c5SAndroid Build Coastguard Worker 775*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(prepareRenderPass(context, &mRenderPassDesc, command)); 776*8975f5c5SAndroid Build Coastguard Worker bool renderPassChanged = !oldRenderPassDesc.equalIgnoreLoadStoreOptions(mRenderPassDesc); 777*8975f5c5SAndroid Build Coastguard Worker 778*8975f5c5SAndroid Build Coastguard Worker if (mustNotifyContext || renderPassChanged) 779*8975f5c5SAndroid Build Coastguard Worker { 780*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *currentDrawFramebuffer = 781*8975f5c5SAndroid Build Coastguard Worker mtl::GetImpl(context->getState().getDrawFramebuffer()); 782*8975f5c5SAndroid Build Coastguard Worker if (currentDrawFramebuffer == this) 783*8975f5c5SAndroid Build Coastguard Worker { 784*8975f5c5SAndroid Build Coastguard Worker contextMtl->onDrawFrameBufferChangedState(context, this, renderPassChanged); 785*8975f5c5SAndroid Build Coastguard Worker } 786*8975f5c5SAndroid Build Coastguard Worker 787*8975f5c5SAndroid Build Coastguard Worker // Recreate pixel reading buffer if needed in future. 788*8975f5c5SAndroid Build Coastguard Worker mReadPixelBuffer = nullptr; 789*8975f5c5SAndroid Build Coastguard Worker } 790*8975f5c5SAndroid Build Coastguard Worker 791*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 792*8975f5c5SAndroid Build Coastguard Worker} 793*8975f5c5SAndroid Build Coastguard Worker 794*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::getSamplePosition(const gl::Context *context, 795*8975f5c5SAndroid Build Coastguard Worker size_t index, 796*8975f5c5SAndroid Build Coastguard Worker GLfloat *xy) const 797*8975f5c5SAndroid Build Coastguard Worker{ 798*8975f5c5SAndroid Build Coastguard Worker rx::GetSamplePosition(getSamples(), index, xy); 799*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 800*8975f5c5SAndroid Build Coastguard Worker} 801*8975f5c5SAndroid Build Coastguard Worker 802*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::prepareForUse(const gl::Context *context) const 803*8975f5c5SAndroid Build Coastguard Worker{ 804*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer) 805*8975f5c5SAndroid Build Coastguard Worker { 806*8975f5c5SAndroid Build Coastguard Worker // Backbuffer might obtain new drawable, which means it might change the 807*8975f5c5SAndroid Build Coastguard Worker // the native texture used as the target of the render pass. 808*8975f5c5SAndroid Build Coastguard Worker // We need to call this before creating render encoder. 809*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBackbuffer->ensureCurrentDrawableObtained(context)); 810*8975f5c5SAndroid Build Coastguard Worker 811*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer->hasRobustResourceInit()) 812*8975f5c5SAndroid Build Coastguard Worker { 813*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBackbuffer->initializeContents(context, GL_BACK, gl::ImageIndex::Make2D(0))); 814*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer->hasDepthStencil()) 815*8975f5c5SAndroid Build Coastguard Worker { 816*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 817*8975f5c5SAndroid Build Coastguard Worker mBackbuffer->initializeContents(context, GL_DEPTH, gl::ImageIndex::Make2D(0))); 818*8975f5c5SAndroid Build Coastguard Worker } 819*8975f5c5SAndroid Build Coastguard Worker } 820*8975f5c5SAndroid Build Coastguard Worker } 821*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 822*8975f5c5SAndroid Build Coastguard Worker} 823*8975f5c5SAndroid Build Coastguard Worker 824*8975f5c5SAndroid Build Coastguard WorkerRenderTargetMtl *FramebufferMtl::getColorReadRenderTarget(const gl::Context *context) const 825*8975f5c5SAndroid Build Coastguard Worker{ 826*8975f5c5SAndroid Build Coastguard Worker if (mState.getReadIndex() >= mColorRenderTargets.size()) 827*8975f5c5SAndroid Build Coastguard Worker { 828*8975f5c5SAndroid Build Coastguard Worker return nullptr; 829*8975f5c5SAndroid Build Coastguard Worker } 830*8975f5c5SAndroid Build Coastguard Worker 831*8975f5c5SAndroid Build Coastguard Worker if (IsError(prepareForUse(context))) 832*8975f5c5SAndroid Build Coastguard Worker { 833*8975f5c5SAndroid Build Coastguard Worker return nullptr; 834*8975f5c5SAndroid Build Coastguard Worker } 835*8975f5c5SAndroid Build Coastguard Worker 836*8975f5c5SAndroid Build Coastguard Worker return mColorRenderTargets[mState.getReadIndex()]; 837*8975f5c5SAndroid Build Coastguard Worker} 838*8975f5c5SAndroid Build Coastguard Worker 839*8975f5c5SAndroid Build Coastguard WorkerRenderTargetMtl *FramebufferMtl::getColorReadRenderTargetNoCache(const gl::Context *context) const 840*8975f5c5SAndroid Build Coastguard Worker{ 841*8975f5c5SAndroid Build Coastguard Worker if (mState.getReadIndex() >= mColorRenderTargets.size()) 842*8975f5c5SAndroid Build Coastguard Worker { 843*8975f5c5SAndroid Build Coastguard Worker return nullptr; 844*8975f5c5SAndroid Build Coastguard Worker } 845*8975f5c5SAndroid Build Coastguard Worker 846*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer) 847*8975f5c5SAndroid Build Coastguard Worker { 848*8975f5c5SAndroid Build Coastguard Worker // If we have a backbuffer/window surface, we can take the old path here and return 849*8975f5c5SAndroid Build Coastguard Worker // the cached color render target. 850*8975f5c5SAndroid Build Coastguard Worker return getColorReadRenderTarget(context); 851*8975f5c5SAndroid Build Coastguard Worker } 852*8975f5c5SAndroid Build Coastguard Worker // If we have no backbuffer, get the attachment from state color attachments, as it may have 853*8975f5c5SAndroid Build Coastguard Worker // changed before syncing. 854*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *attachment = mState.getColorAttachment(mState.getReadIndex()); 855*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *currentTarget = nullptr; 856*8975f5c5SAndroid Build Coastguard Worker if (attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(), 857*8975f5c5SAndroid Build Coastguard Worker ¤tTarget) == angle::Result::Stop) 858*8975f5c5SAndroid Build Coastguard Worker { 859*8975f5c5SAndroid Build Coastguard Worker return nullptr; 860*8975f5c5SAndroid Build Coastguard Worker } 861*8975f5c5SAndroid Build Coastguard Worker return currentTarget; 862*8975f5c5SAndroid Build Coastguard Worker} 863*8975f5c5SAndroid Build Coastguard Worker 864*8975f5c5SAndroid Build Coastguard Workerint FramebufferMtl::getSamples() const 865*8975f5c5SAndroid Build Coastguard Worker{ 866*8975f5c5SAndroid Build Coastguard Worker return mRenderPassDesc.rasterSampleCount; 867*8975f5c5SAndroid Build Coastguard Worker} 868*8975f5c5SAndroid Build Coastguard Worker 869*8975f5c5SAndroid Build Coastguard Workergl::Rectangle FramebufferMtl::getCompleteRenderArea() const 870*8975f5c5SAndroid Build Coastguard Worker{ 871*8975f5c5SAndroid Build Coastguard Worker return gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height); 872*8975f5c5SAndroid Build Coastguard Worker} 873*8975f5c5SAndroid Build Coastguard Worker 874*8975f5c5SAndroid Build Coastguard Workerbool FramebufferMtl::renderPassHasStarted(ContextMtl *contextMtl) const 875*8975f5c5SAndroid Build Coastguard Worker{ 876*8975f5c5SAndroid Build Coastguard Worker return contextMtl->hasStartedRenderPass(mRenderPassDesc); 877*8975f5c5SAndroid Build Coastguard Worker} 878*8975f5c5SAndroid Build Coastguard Worker 879*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::ensureRenderPassStarted(const gl::Context *context, 880*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder **encoderOut) 881*8975f5c5SAndroid Build Coastguard Worker{ 882*8975f5c5SAndroid Build Coastguard Worker return ensureRenderPassStarted(context, mRenderPassDesc, encoderOut); 883*8975f5c5SAndroid Build Coastguard Worker} 884*8975f5c5SAndroid Build Coastguard Worker 885*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::ensureRenderPassStarted(const gl::Context *context, 886*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassDesc &desc, 887*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder **encoderOut) 888*8975f5c5SAndroid Build Coastguard Worker{ 889*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 890*8975f5c5SAndroid Build Coastguard Worker 891*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = contextMtl->getRenderCommandEncoder(); 892*8975f5c5SAndroid Build Coastguard Worker if (encoder && encoder->getSerial() == mStartedRenderEncoderSerial) 893*8975f5c5SAndroid Build Coastguard Worker { 894*8975f5c5SAndroid Build Coastguard Worker // Already started. 895*8975f5c5SAndroid Build Coastguard Worker *encoderOut = encoder; 896*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 897*8975f5c5SAndroid Build Coastguard Worker } 898*8975f5c5SAndroid Build Coastguard Worker 899*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(prepareForUse(context)); 900*8975f5c5SAndroid Build Coastguard Worker 901*8975f5c5SAndroid Build Coastguard Worker // Only support ensureRenderPassStarted() with different load & store options only. The 902*8975f5c5SAndroid Build Coastguard Worker // texture, level, slice must be the same. 903*8975f5c5SAndroid Build Coastguard Worker ASSERT(desc.equalIgnoreLoadStoreOptions(mRenderPassDesc)); 904*8975f5c5SAndroid Build Coastguard Worker 905*8975f5c5SAndroid Build Coastguard Worker encoder = contextMtl->getRenderPassCommandEncoder(desc); 906*8975f5c5SAndroid Build Coastguard Worker mStartedRenderEncoderSerial = encoder->getSerial(); 907*8975f5c5SAndroid Build Coastguard Worker 908*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(unresolveIfNeeded(context, encoder)); 909*8975f5c5SAndroid Build Coastguard Worker 910*8975f5c5SAndroid Build Coastguard Worker if (mRenderPassCleanStart) 911*8975f5c5SAndroid Build Coastguard Worker { 912*8975f5c5SAndroid Build Coastguard Worker // After a clean start we should reset the loadOp to MTLLoadActionLoad in case this render 913*8975f5c5SAndroid Build Coastguard Worker // pass could be interrupted by a conversion compute shader pass then being resumed later. 914*8975f5c5SAndroid Build Coastguard Worker mRenderPassCleanStart = false; 915*8975f5c5SAndroid Build Coastguard Worker for (mtl::RenderPassColorAttachmentDesc &colorAttachment : mRenderPassDesc.colorAttachments) 916*8975f5c5SAndroid Build Coastguard Worker { 917*8975f5c5SAndroid Build Coastguard Worker colorAttachment.loadAction = MTLLoadActionLoad; 918*8975f5c5SAndroid Build Coastguard Worker } 919*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.depthAttachment.loadAction = MTLLoadActionLoad; 920*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.stencilAttachment.loadAction = MTLLoadActionLoad; 921*8975f5c5SAndroid Build Coastguard Worker } 922*8975f5c5SAndroid Build Coastguard Worker 923*8975f5c5SAndroid Build Coastguard Worker *encoderOut = encoder; 924*8975f5c5SAndroid Build Coastguard Worker 925*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 926*8975f5c5SAndroid Build Coastguard Worker} 927*8975f5c5SAndroid Build Coastguard Worker 928*8975f5c5SAndroid Build Coastguard Workervoid FramebufferMtl::setLoadStoreActionOnRenderPassFirstStart( 929*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassAttachmentDesc *attachmentOut, 930*8975f5c5SAndroid Build Coastguard Worker const bool forceDepthStencilMultisampleLoad) 931*8975f5c5SAndroid Build Coastguard Worker{ 932*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderPassCleanStart); 933*8975f5c5SAndroid Build Coastguard Worker 934*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassAttachmentDesc &attachment = *attachmentOut; 935*8975f5c5SAndroid Build Coastguard Worker 936*8975f5c5SAndroid Build Coastguard Worker if (!forceDepthStencilMultisampleLoad && attachment.storeAction == MTLStoreActionDontCare) 937*8975f5c5SAndroid Build Coastguard Worker { 938*8975f5c5SAndroid Build Coastguard Worker // If we previously discarded attachment's content, then don't need to load it. 939*8975f5c5SAndroid Build Coastguard Worker attachment.loadAction = MTLLoadActionDontCare; 940*8975f5c5SAndroid Build Coastguard Worker } 941*8975f5c5SAndroid Build Coastguard Worker else 942*8975f5c5SAndroid Build Coastguard Worker { 943*8975f5c5SAndroid Build Coastguard Worker attachment.loadAction = MTLLoadActionLoad; 944*8975f5c5SAndroid Build Coastguard Worker } 945*8975f5c5SAndroid Build Coastguard Worker 946*8975f5c5SAndroid Build Coastguard Worker if (attachment.hasImplicitMSTexture()) 947*8975f5c5SAndroid Build Coastguard Worker { 948*8975f5c5SAndroid Build Coastguard Worker attachment.storeAction = MTLStoreActionStoreAndMultisampleResolve; 949*8975f5c5SAndroid Build Coastguard Worker } 950*8975f5c5SAndroid Build Coastguard Worker else 951*8975f5c5SAndroid Build Coastguard Worker { 952*8975f5c5SAndroid Build Coastguard Worker attachment.storeAction = MTLStoreActionStore; // Default action is store 953*8975f5c5SAndroid Build Coastguard Worker } 954*8975f5c5SAndroid Build Coastguard Worker} 955*8975f5c5SAndroid Build Coastguard Worker 956*8975f5c5SAndroid Build Coastguard Workervoid FramebufferMtl::onStartedDrawingToFrameBuffer(const gl::Context *context) 957*8975f5c5SAndroid Build Coastguard Worker{ 958*8975f5c5SAndroid Build Coastguard Worker mRenderPassCleanStart = true; 959*8975f5c5SAndroid Build Coastguard Worker 960*8975f5c5SAndroid Build Coastguard Worker // If any of the render targets need to load their multisample textures, we should do the same 961*8975f5c5SAndroid Build Coastguard Worker // for depth/stencil. 962*8975f5c5SAndroid Build Coastguard Worker bool forceDepthStencilMultisampleLoad = false; 963*8975f5c5SAndroid Build Coastguard Worker 964*8975f5c5SAndroid Build Coastguard Worker // Compute loadOp based on previous storeOp and reset storeOp flags: 965*8975f5c5SAndroid Build Coastguard Worker for (mtl::RenderPassColorAttachmentDesc &colorAttachment : mRenderPassDesc.colorAttachments) 966*8975f5c5SAndroid Build Coastguard Worker { 967*8975f5c5SAndroid Build Coastguard Worker forceDepthStencilMultisampleLoad |= 968*8975f5c5SAndroid Build Coastguard Worker colorAttachment.storeAction == MTLStoreActionStoreAndMultisampleResolve; 969*8975f5c5SAndroid Build Coastguard Worker setLoadStoreActionOnRenderPassFirstStart(&colorAttachment, false); 970*8975f5c5SAndroid Build Coastguard Worker } 971*8975f5c5SAndroid Build Coastguard Worker // Depth load/store 972*8975f5c5SAndroid Build Coastguard Worker setLoadStoreActionOnRenderPassFirstStart(&mRenderPassDesc.depthAttachment, 973*8975f5c5SAndroid Build Coastguard Worker forceDepthStencilMultisampleLoad); 974*8975f5c5SAndroid Build Coastguard Worker 975*8975f5c5SAndroid Build Coastguard Worker // Stencil load/store 976*8975f5c5SAndroid Build Coastguard Worker setLoadStoreActionOnRenderPassFirstStart(&mRenderPassDesc.stencilAttachment, 977*8975f5c5SAndroid Build Coastguard Worker forceDepthStencilMultisampleLoad); 978*8975f5c5SAndroid Build Coastguard Worker} 979*8975f5c5SAndroid Build Coastguard Worker 980*8975f5c5SAndroid Build Coastguard Workervoid FramebufferMtl::onFrameEnd(const gl::Context *context) 981*8975f5c5SAndroid Build Coastguard Worker{ 982*8975f5c5SAndroid Build Coastguard Worker if (!mBackbuffer || mBackbuffer->preserveBuffer()) 983*8975f5c5SAndroid Build Coastguard Worker { 984*8975f5c5SAndroid Build Coastguard Worker return; 985*8975f5c5SAndroid Build Coastguard Worker } 986*8975f5c5SAndroid Build Coastguard Worker 987*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 988*8975f5c5SAndroid Build Coastguard Worker // Always discard default FBO's depth stencil & multisample buffers at the end of the frame: 989*8975f5c5SAndroid Build Coastguard Worker if (this->renderPassHasStarted(contextMtl)) 990*8975f5c5SAndroid Build Coastguard Worker { 991*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = contextMtl->getRenderCommandEncoder(); 992*8975f5c5SAndroid Build Coastguard Worker 993*8975f5c5SAndroid Build Coastguard Worker constexpr GLenum dsAttachments[] = {GL_DEPTH, GL_STENCIL}; 994*8975f5c5SAndroid Build Coastguard Worker (void)invalidateImpl(context, 2, dsAttachments); 995*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer->getSamples() > 1) 996*8975f5c5SAndroid Build Coastguard Worker { 997*8975f5c5SAndroid Build Coastguard Worker encoder->setColorStoreAction(MTLStoreActionMultisampleResolve, 0); 998*8975f5c5SAndroid Build Coastguard Worker } 999*8975f5c5SAndroid Build Coastguard Worker 1000*8975f5c5SAndroid Build Coastguard Worker contextMtl->endEncoding(false); 1001*8975f5c5SAndroid Build Coastguard Worker 1002*8975f5c5SAndroid Build Coastguard Worker // Reset discard flag. 1003*8975f5c5SAndroid Build Coastguard Worker onStartedDrawingToFrameBuffer(context); 1004*8975f5c5SAndroid Build Coastguard Worker } 1005*8975f5c5SAndroid Build Coastguard Worker} 1006*8975f5c5SAndroid Build Coastguard Worker 1007*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::updateColorRenderTarget(const gl::Context *context, 1008*8975f5c5SAndroid Build Coastguard Worker size_t colorIndexGL) 1009*8975f5c5SAndroid Build Coastguard Worker{ 1010*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndexGL < mColorRenderTargets.size()); 1011*8975f5c5SAndroid Build Coastguard Worker // Reset load store action 1012*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.colorAttachments[colorIndexGL].reset(); 1013*8975f5c5SAndroid Build Coastguard Worker return updateCachedRenderTarget(context, mState.getColorAttachment(colorIndexGL), 1014*8975f5c5SAndroid Build Coastguard Worker &mColorRenderTargets[colorIndexGL]); 1015*8975f5c5SAndroid Build Coastguard Worker} 1016*8975f5c5SAndroid Build Coastguard Worker 1017*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::updateDepthRenderTarget(const gl::Context *context) 1018*8975f5c5SAndroid Build Coastguard Worker{ 1019*8975f5c5SAndroid Build Coastguard Worker // Reset load store action 1020*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.depthAttachment.reset(); 1021*8975f5c5SAndroid Build Coastguard Worker return updateCachedRenderTarget(context, mState.getDepthAttachment(), &mDepthRenderTarget); 1022*8975f5c5SAndroid Build Coastguard Worker} 1023*8975f5c5SAndroid Build Coastguard Worker 1024*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::updateStencilRenderTarget(const gl::Context *context) 1025*8975f5c5SAndroid Build Coastguard Worker{ 1026*8975f5c5SAndroid Build Coastguard Worker // Reset load store action 1027*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.stencilAttachment.reset(); 1028*8975f5c5SAndroid Build Coastguard Worker return updateCachedRenderTarget(context, mState.getStencilAttachment(), &mStencilRenderTarget); 1029*8975f5c5SAndroid Build Coastguard Worker} 1030*8975f5c5SAndroid Build Coastguard Worker 1031*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::updateCachedRenderTarget(const gl::Context *context, 1032*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *attachment, 1033*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl **cachedRenderTarget) 1034*8975f5c5SAndroid Build Coastguard Worker{ 1035*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *newRenderTarget = nullptr; 1036*8975f5c5SAndroid Build Coastguard Worker if (attachment) 1037*8975f5c5SAndroid Build Coastguard Worker { 1038*8975f5c5SAndroid Build Coastguard Worker ASSERT(attachment->isAttached()); 1039*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(), 1040*8975f5c5SAndroid Build Coastguard Worker &newRenderTarget)); 1041*8975f5c5SAndroid Build Coastguard Worker } 1042*8975f5c5SAndroid Build Coastguard Worker *cachedRenderTarget = newRenderTarget; 1043*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1044*8975f5c5SAndroid Build Coastguard Worker} 1045*8975f5c5SAndroid Build Coastguard Worker 1046*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::prepareRenderPass(const gl::Context *context, 1047*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc *pDescOut, 1048*8975f5c5SAndroid Build Coastguard Worker gl::Command command) 1049*8975f5c5SAndroid Build Coastguard Worker{ 1050*8975f5c5SAndroid Build Coastguard Worker // Skip incompatible attachments for draw ops to avoid triggering Metal runtime failures. 1051*8975f5c5SAndroid Build Coastguard Worker const gl::DrawBufferMask incompatibleAttachments = 1052*8975f5c5SAndroid Build Coastguard Worker (command == gl::Command::Draw) ? mtl::GetImpl(context)->getIncompatibleAttachments() 1053*8975f5c5SAndroid Build Coastguard Worker : gl::DrawBufferMask(); 1054*8975f5c5SAndroid Build Coastguard Worker const gl::DrawBufferMask enabledDrawBuffers = 1055*8975f5c5SAndroid Build Coastguard Worker getState().getEnabledDrawBuffers() & ~incompatibleAttachments; 1056*8975f5c5SAndroid Build Coastguard Worker 1057*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc &desc = *pDescOut; 1058*8975f5c5SAndroid Build Coastguard Worker 1059*8975f5c5SAndroid Build Coastguard Worker mRenderPassFirstColorAttachmentFormat = nullptr; 1060*8975f5c5SAndroid Build Coastguard Worker mRenderPassAttachmentsSameColorType = true; 1061*8975f5c5SAndroid Build Coastguard Worker uint32_t maxColorAttachments = static_cast<uint32_t>(mState.getColorAttachments().size()); 1062*8975f5c5SAndroid Build Coastguard Worker desc.numColorAttachments = 0; 1063*8975f5c5SAndroid Build Coastguard Worker desc.rasterSampleCount = 1; 1064*8975f5c5SAndroid Build Coastguard Worker for (uint32_t colorIndexGL = 0; colorIndexGL < maxColorAttachments; ++colorIndexGL) 1065*8975f5c5SAndroid Build Coastguard Worker { 1066*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndexGL < mColorRenderTargets.size()); 1067*8975f5c5SAndroid Build Coastguard Worker 1068*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassColorAttachmentDesc &colorAttachment = desc.colorAttachments[colorIndexGL]; 1069*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *colorRenderTarget = mColorRenderTargets[colorIndexGL]; 1070*8975f5c5SAndroid Build Coastguard Worker 1071*8975f5c5SAndroid Build Coastguard Worker // GL allows data types of fragment shader color outputs to be incompatible with disabled 1072*8975f5c5SAndroid Build Coastguard Worker // color attachments. To prevent various Metal validation issues, assign textures only to 1073*8975f5c5SAndroid Build Coastguard Worker // enabled attachments. 1074*8975f5c5SAndroid Build Coastguard Worker if (colorRenderTarget && enabledDrawBuffers.test(colorIndexGL)) 1075*8975f5c5SAndroid Build Coastguard Worker { 1076*8975f5c5SAndroid Build Coastguard Worker colorRenderTarget->toRenderPassAttachmentDesc(&colorAttachment); 1077*8975f5c5SAndroid Build Coastguard Worker 1078*8975f5c5SAndroid Build Coastguard Worker desc.numColorAttachments = std::max(desc.numColorAttachments, colorIndexGL + 1); 1079*8975f5c5SAndroid Build Coastguard Worker desc.rasterSampleCount = 1080*8975f5c5SAndroid Build Coastguard Worker std::max(desc.rasterSampleCount, colorRenderTarget->getRenderSamples()); 1081*8975f5c5SAndroid Build Coastguard Worker 1082*8975f5c5SAndroid Build Coastguard Worker if (!mRenderPassFirstColorAttachmentFormat) 1083*8975f5c5SAndroid Build Coastguard Worker { 1084*8975f5c5SAndroid Build Coastguard Worker mRenderPassFirstColorAttachmentFormat = &colorRenderTarget->getFormat(); 1085*8975f5c5SAndroid Build Coastguard Worker } 1086*8975f5c5SAndroid Build Coastguard Worker else 1087*8975f5c5SAndroid Build Coastguard Worker { 1088*8975f5c5SAndroid Build Coastguard Worker if (mRenderPassFirstColorAttachmentFormat->actualAngleFormat().isSint() != 1089*8975f5c5SAndroid Build Coastguard Worker colorRenderTarget->getFormat().actualAngleFormat().isSint() || 1090*8975f5c5SAndroid Build Coastguard Worker mRenderPassFirstColorAttachmentFormat->actualAngleFormat().isUint() != 1091*8975f5c5SAndroid Build Coastguard Worker colorRenderTarget->getFormat().actualAngleFormat().isUint()) 1092*8975f5c5SAndroid Build Coastguard Worker { 1093*8975f5c5SAndroid Build Coastguard Worker mRenderPassAttachmentsSameColorType = false; 1094*8975f5c5SAndroid Build Coastguard Worker } 1095*8975f5c5SAndroid Build Coastguard Worker } 1096*8975f5c5SAndroid Build Coastguard Worker } 1097*8975f5c5SAndroid Build Coastguard Worker else 1098*8975f5c5SAndroid Build Coastguard Worker { 1099*8975f5c5SAndroid Build Coastguard Worker colorAttachment.reset(); 1100*8975f5c5SAndroid Build Coastguard Worker } 1101*8975f5c5SAndroid Build Coastguard Worker } 1102*8975f5c5SAndroid Build Coastguard Worker 1103*8975f5c5SAndroid Build Coastguard Worker if (mDepthRenderTarget) 1104*8975f5c5SAndroid Build Coastguard Worker { 1105*8975f5c5SAndroid Build Coastguard Worker mDepthRenderTarget->toRenderPassAttachmentDesc(&desc.depthAttachment); 1106*8975f5c5SAndroid Build Coastguard Worker desc.rasterSampleCount = 1107*8975f5c5SAndroid Build Coastguard Worker std::max(desc.rasterSampleCount, mDepthRenderTarget->getRenderSamples()); 1108*8975f5c5SAndroid Build Coastguard Worker } 1109*8975f5c5SAndroid Build Coastguard Worker else 1110*8975f5c5SAndroid Build Coastguard Worker { 1111*8975f5c5SAndroid Build Coastguard Worker desc.depthAttachment.reset(); 1112*8975f5c5SAndroid Build Coastguard Worker } 1113*8975f5c5SAndroid Build Coastguard Worker 1114*8975f5c5SAndroid Build Coastguard Worker if (mStencilRenderTarget) 1115*8975f5c5SAndroid Build Coastguard Worker { 1116*8975f5c5SAndroid Build Coastguard Worker mStencilRenderTarget->toRenderPassAttachmentDesc(&desc.stencilAttachment); 1117*8975f5c5SAndroid Build Coastguard Worker desc.rasterSampleCount = 1118*8975f5c5SAndroid Build Coastguard Worker std::max(desc.rasterSampleCount, mStencilRenderTarget->getRenderSamples()); 1119*8975f5c5SAndroid Build Coastguard Worker } 1120*8975f5c5SAndroid Build Coastguard Worker else 1121*8975f5c5SAndroid Build Coastguard Worker { 1122*8975f5c5SAndroid Build Coastguard Worker desc.stencilAttachment.reset(); 1123*8975f5c5SAndroid Build Coastguard Worker } 1124*8975f5c5SAndroid Build Coastguard Worker 1125*8975f5c5SAndroid Build Coastguard Worker if (desc.numColorAttachments == 0 && mDepthRenderTarget == nullptr && 1126*8975f5c5SAndroid Build Coastguard Worker mStencilRenderTarget == nullptr) 1127*8975f5c5SAndroid Build Coastguard Worker { 1128*8975f5c5SAndroid Build Coastguard Worker desc.defaultWidth = mState.getDefaultWidth(); 1129*8975f5c5SAndroid Build Coastguard Worker desc.defaultHeight = mState.getDefaultHeight(); 1130*8975f5c5SAndroid Build Coastguard Worker } 1131*8975f5c5SAndroid Build Coastguard Worker 1132*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1133*8975f5c5SAndroid Build Coastguard Worker} 1134*8975f5c5SAndroid Build Coastguard Worker 1135*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearWithLoadOp(const gl::Context *context, 1136*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers, 1137*8975f5c5SAndroid Build Coastguard Worker const mtl::ClearRectParams &clearOpts) 1138*8975f5c5SAndroid Build Coastguard Worker{ 1139*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1140*8975f5c5SAndroid Build Coastguard Worker bool startedRenderPass = contextMtl->hasStartedRenderPass(mRenderPassDesc); 1141*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = nullptr; 1142*8975f5c5SAndroid Build Coastguard Worker 1143*8975f5c5SAndroid Build Coastguard Worker if (startedRenderPass) 1144*8975f5c5SAndroid Build Coastguard Worker { 1145*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderPassStarted(context, &encoder)); 1146*8975f5c5SAndroid Build Coastguard Worker if (encoder->hasDrawCalls()) 1147*8975f5c5SAndroid Build Coastguard Worker { 1148*8975f5c5SAndroid Build Coastguard Worker // Render pass already has draw calls recorded, it is better to use clear with draw 1149*8975f5c5SAndroid Build Coastguard Worker // operation. 1150*8975f5c5SAndroid Build Coastguard Worker return clearWithDraw(context, clearColorBuffers, clearOpts); 1151*8975f5c5SAndroid Build Coastguard Worker } 1152*8975f5c5SAndroid Build Coastguard Worker else 1153*8975f5c5SAndroid Build Coastguard Worker { 1154*8975f5c5SAndroid Build Coastguard Worker // If render pass has started but there is no draw call yet. It is OK to change the 1155*8975f5c5SAndroid Build Coastguard Worker // loadOp. 1156*8975f5c5SAndroid Build Coastguard Worker return clearWithLoadOpRenderPassStarted(context, clearColorBuffers, clearOpts, encoder); 1157*8975f5c5SAndroid Build Coastguard Worker } 1158*8975f5c5SAndroid Build Coastguard Worker } 1159*8975f5c5SAndroid Build Coastguard Worker else 1160*8975f5c5SAndroid Build Coastguard Worker { 1161*8975f5c5SAndroid Build Coastguard Worker return clearWithLoadOpRenderPassNotStarted(context, clearColorBuffers, clearOpts); 1162*8975f5c5SAndroid Build Coastguard Worker } 1163*8975f5c5SAndroid Build Coastguard Worker} 1164*8975f5c5SAndroid Build Coastguard Worker 1165*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearWithLoadOpRenderPassNotStarted( 1166*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context, 1167*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers, 1168*8975f5c5SAndroid Build Coastguard Worker const mtl::ClearRectParams &clearOpts) 1169*8975f5c5SAndroid Build Coastguard Worker{ 1170*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc tempDesc = mRenderPassDesc; 1171*8975f5c5SAndroid Build Coastguard Worker 1172*8975f5c5SAndroid Build Coastguard Worker for (uint32_t colorIndexGL = 0; colorIndexGL < tempDesc.numColorAttachments; ++colorIndexGL) 1173*8975f5c5SAndroid Build Coastguard Worker { 1174*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndexGL < tempDesc.colorAttachments.size()); 1175*8975f5c5SAndroid Build Coastguard Worker 1176*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassColorAttachmentDesc &colorAttachment = 1177*8975f5c5SAndroid Build Coastguard Worker tempDesc.colorAttachments[colorIndexGL]; 1178*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &texture = colorAttachment.texture; 1179*8975f5c5SAndroid Build Coastguard Worker 1180*8975f5c5SAndroid Build Coastguard Worker if (clearColorBuffers.test(colorIndexGL)) 1181*8975f5c5SAndroid Build Coastguard Worker { 1182*8975f5c5SAndroid Build Coastguard Worker colorAttachment.loadAction = MTLLoadActionClear; 1183*8975f5c5SAndroid Build Coastguard Worker OverrideMTLClearColor(texture, clearOpts.clearColor.value(), 1184*8975f5c5SAndroid Build Coastguard Worker &colorAttachment.clearColor); 1185*8975f5c5SAndroid Build Coastguard Worker } 1186*8975f5c5SAndroid Build Coastguard Worker else 1187*8975f5c5SAndroid Build Coastguard Worker { 1188*8975f5c5SAndroid Build Coastguard Worker colorAttachment.loadAction = MTLLoadActionLoad; 1189*8975f5c5SAndroid Build Coastguard Worker } 1190*8975f5c5SAndroid Build Coastguard Worker 1191*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.hasImplicitMSTexture()) 1192*8975f5c5SAndroid Build Coastguard Worker { 1193*8975f5c5SAndroid Build Coastguard Worker colorAttachment.storeAction = MTLStoreActionStoreAndMultisampleResolve; 1194*8975f5c5SAndroid Build Coastguard Worker } 1195*8975f5c5SAndroid Build Coastguard Worker else 1196*8975f5c5SAndroid Build Coastguard Worker { 1197*8975f5c5SAndroid Build Coastguard Worker colorAttachment.storeAction = MTLStoreActionStore; 1198*8975f5c5SAndroid Build Coastguard Worker } 1199*8975f5c5SAndroid Build Coastguard Worker } 1200*8975f5c5SAndroid Build Coastguard Worker 1201*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearDepth.valid()) 1202*8975f5c5SAndroid Build Coastguard Worker { 1203*8975f5c5SAndroid Build Coastguard Worker tempDesc.depthAttachment.loadAction = MTLLoadActionClear; 1204*8975f5c5SAndroid Build Coastguard Worker tempDesc.depthAttachment.clearDepth = clearOpts.clearDepth.value(); 1205*8975f5c5SAndroid Build Coastguard Worker } 1206*8975f5c5SAndroid Build Coastguard Worker else 1207*8975f5c5SAndroid Build Coastguard Worker { 1208*8975f5c5SAndroid Build Coastguard Worker tempDesc.depthAttachment.loadAction = MTLLoadActionLoad; 1209*8975f5c5SAndroid Build Coastguard Worker } 1210*8975f5c5SAndroid Build Coastguard Worker 1211*8975f5c5SAndroid Build Coastguard Worker if (tempDesc.depthAttachment.hasImplicitMSTexture()) 1212*8975f5c5SAndroid Build Coastguard Worker { 1213*8975f5c5SAndroid Build Coastguard Worker tempDesc.depthAttachment.storeAction = MTLStoreActionStoreAndMultisampleResolve; 1214*8975f5c5SAndroid Build Coastguard Worker } 1215*8975f5c5SAndroid Build Coastguard Worker else 1216*8975f5c5SAndroid Build Coastguard Worker { 1217*8975f5c5SAndroid Build Coastguard Worker tempDesc.depthAttachment.storeAction = MTLStoreActionStore; 1218*8975f5c5SAndroid Build Coastguard Worker } 1219*8975f5c5SAndroid Build Coastguard Worker 1220*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearStencil.valid()) 1221*8975f5c5SAndroid Build Coastguard Worker { 1222*8975f5c5SAndroid Build Coastguard Worker tempDesc.stencilAttachment.loadAction = MTLLoadActionClear; 1223*8975f5c5SAndroid Build Coastguard Worker tempDesc.stencilAttachment.clearStencil = clearOpts.clearStencil.value(); 1224*8975f5c5SAndroid Build Coastguard Worker } 1225*8975f5c5SAndroid Build Coastguard Worker else 1226*8975f5c5SAndroid Build Coastguard Worker { 1227*8975f5c5SAndroid Build Coastguard Worker tempDesc.stencilAttachment.loadAction = MTLLoadActionLoad; 1228*8975f5c5SAndroid Build Coastguard Worker } 1229*8975f5c5SAndroid Build Coastguard Worker 1230*8975f5c5SAndroid Build Coastguard Worker if (tempDesc.stencilAttachment.hasImplicitMSTexture()) 1231*8975f5c5SAndroid Build Coastguard Worker { 1232*8975f5c5SAndroid Build Coastguard Worker tempDesc.stencilAttachment.storeAction = MTLStoreActionStoreAndMultisampleResolve; 1233*8975f5c5SAndroid Build Coastguard Worker } 1234*8975f5c5SAndroid Build Coastguard Worker else 1235*8975f5c5SAndroid Build Coastguard Worker { 1236*8975f5c5SAndroid Build Coastguard Worker tempDesc.stencilAttachment.storeAction = MTLStoreActionStore; 1237*8975f5c5SAndroid Build Coastguard Worker } 1238*8975f5c5SAndroid Build Coastguard Worker 1239*8975f5c5SAndroid Build Coastguard Worker // Start new render encoder with loadOp=Clear 1240*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder; 1241*8975f5c5SAndroid Build Coastguard Worker return ensureRenderPassStarted(context, tempDesc, &encoder); 1242*8975f5c5SAndroid Build Coastguard Worker} 1243*8975f5c5SAndroid Build Coastguard Worker 1244*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearWithLoadOpRenderPassStarted( 1245*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context, 1246*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers, 1247*8975f5c5SAndroid Build Coastguard Worker const mtl::ClearRectParams &clearOpts, 1248*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder) 1249*8975f5c5SAndroid Build Coastguard Worker{ 1250*8975f5c5SAndroid Build Coastguard Worker ASSERT(!encoder->hasDrawCalls()); 1251*8975f5c5SAndroid Build Coastguard Worker 1252*8975f5c5SAndroid Build Coastguard Worker for (uint32_t colorIndexGL = 0; colorIndexGL < mRenderPassDesc.numColorAttachments; 1253*8975f5c5SAndroid Build Coastguard Worker ++colorIndexGL) 1254*8975f5c5SAndroid Build Coastguard Worker { 1255*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndexGL < mRenderPassDesc.colorAttachments.size()); 1256*8975f5c5SAndroid Build Coastguard Worker 1257*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassColorAttachmentDesc &colorAttachment = 1258*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.colorAttachments[colorIndexGL]; 1259*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &texture = colorAttachment.texture; 1260*8975f5c5SAndroid Build Coastguard Worker 1261*8975f5c5SAndroid Build Coastguard Worker if (clearColorBuffers.test(colorIndexGL)) 1262*8975f5c5SAndroid Build Coastguard Worker { 1263*8975f5c5SAndroid Build Coastguard Worker MTLClearColor clearVal; 1264*8975f5c5SAndroid Build Coastguard Worker OverrideMTLClearColor(texture, clearOpts.clearColor.value(), &clearVal); 1265*8975f5c5SAndroid Build Coastguard Worker 1266*8975f5c5SAndroid Build Coastguard Worker encoder->setColorLoadAction(MTLLoadActionClear, clearVal, colorIndexGL); 1267*8975f5c5SAndroid Build Coastguard Worker } 1268*8975f5c5SAndroid Build Coastguard Worker } 1269*8975f5c5SAndroid Build Coastguard Worker 1270*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearDepth.valid()) 1271*8975f5c5SAndroid Build Coastguard Worker { 1272*8975f5c5SAndroid Build Coastguard Worker encoder->setDepthLoadAction(MTLLoadActionClear, clearOpts.clearDepth.value()); 1273*8975f5c5SAndroid Build Coastguard Worker } 1274*8975f5c5SAndroid Build Coastguard Worker 1275*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearStencil.valid()) 1276*8975f5c5SAndroid Build Coastguard Worker { 1277*8975f5c5SAndroid Build Coastguard Worker encoder->setStencilLoadAction(MTLLoadActionClear, clearOpts.clearStencil.value()); 1278*8975f5c5SAndroid Build Coastguard Worker } 1279*8975f5c5SAndroid Build Coastguard Worker 1280*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1281*8975f5c5SAndroid Build Coastguard Worker} 1282*8975f5c5SAndroid Build Coastguard Worker 1283*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearWithDraw(const gl::Context *context, 1284*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers, 1285*8975f5c5SAndroid Build Coastguard Worker const mtl::ClearRectParams &clearOpts) 1286*8975f5c5SAndroid Build Coastguard Worker{ 1287*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1288*8975f5c5SAndroid Build Coastguard Worker DisplayMtl *display = contextMtl->getDisplay(); 1289*8975f5c5SAndroid Build Coastguard Worker 1290*8975f5c5SAndroid Build Coastguard Worker if (mRenderPassAttachmentsSameColorType) 1291*8975f5c5SAndroid Build Coastguard Worker { 1292*8975f5c5SAndroid Build Coastguard Worker // Start new render encoder if not already. 1293*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder; 1294*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderPassStarted(context, mRenderPassDesc, &encoder)); 1295*8975f5c5SAndroid Build Coastguard Worker 1296*8975f5c5SAndroid Build Coastguard Worker return display->getUtils().clearWithDraw(context, encoder, clearOpts); 1297*8975f5c5SAndroid Build Coastguard Worker } 1298*8975f5c5SAndroid Build Coastguard Worker 1299*8975f5c5SAndroid Build Coastguard Worker // Not all attachments have the same color type. 1300*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams overrideClearOps = clearOpts; 1301*8975f5c5SAndroid Build Coastguard Worker overrideClearOps.enabledBuffers.reset(); 1302*8975f5c5SAndroid Build Coastguard Worker 1303*8975f5c5SAndroid Build Coastguard Worker // First clear depth/stencil without color attachment 1304*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearDepth.valid() || clearOpts.clearStencil.valid()) 1305*8975f5c5SAndroid Build Coastguard Worker { 1306*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc dsOnlyDesc = mRenderPassDesc; 1307*8975f5c5SAndroid Build Coastguard Worker dsOnlyDesc.numColorAttachments = 0; 1308*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = contextMtl->getRenderPassCommandEncoder(dsOnlyDesc); 1309*8975f5c5SAndroid Build Coastguard Worker 1310*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(display->getUtils().clearWithDraw(context, encoder, overrideClearOps)); 1311*8975f5c5SAndroid Build Coastguard Worker } 1312*8975f5c5SAndroid Build Coastguard Worker 1313*8975f5c5SAndroid Build Coastguard Worker // Clear the color attachment one by one. 1314*8975f5c5SAndroid Build Coastguard Worker overrideClearOps.enabledBuffers.set(0); 1315*8975f5c5SAndroid Build Coastguard Worker for (size_t drawbuffer : clearColorBuffers) 1316*8975f5c5SAndroid Build Coastguard Worker { 1317*8975f5c5SAndroid Build Coastguard Worker if (drawbuffer >= mRenderPassDesc.numColorAttachments) 1318*8975f5c5SAndroid Build Coastguard Worker { 1319*8975f5c5SAndroid Build Coastguard Worker // Iteration over drawbuffer indices always goes in ascending order 1320*8975f5c5SAndroid Build Coastguard Worker break; 1321*8975f5c5SAndroid Build Coastguard Worker } 1322*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *renderTarget = mColorRenderTargets[drawbuffer]; 1323*8975f5c5SAndroid Build Coastguard Worker if (!renderTarget || !renderTarget->getTexture()) 1324*8975f5c5SAndroid Build Coastguard Worker { 1325*8975f5c5SAndroid Build Coastguard Worker continue; 1326*8975f5c5SAndroid Build Coastguard Worker } 1327*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &format = renderTarget->getFormat(); 1328*8975f5c5SAndroid Build Coastguard Worker mtl::PixelType clearColorType = overrideClearOps.clearColor.value().getType(); 1329*8975f5c5SAndroid Build Coastguard Worker if ((clearColorType == mtl::PixelType::Int && !format.actualAngleFormat().isSint()) || 1330*8975f5c5SAndroid Build Coastguard Worker (clearColorType == mtl::PixelType::UInt && !format.actualAngleFormat().isUint()) || 1331*8975f5c5SAndroid Build Coastguard Worker (clearColorType == mtl::PixelType::Float && format.actualAngleFormat().isInt())) 1332*8975f5c5SAndroid Build Coastguard Worker { 1333*8975f5c5SAndroid Build Coastguard Worker continue; 1334*8975f5c5SAndroid Build Coastguard Worker } 1335*8975f5c5SAndroid Build Coastguard Worker 1336*8975f5c5SAndroid Build Coastguard Worker overrideClearOps.clearWriteMaskArray[0] = overrideClearOps.clearWriteMaskArray[drawbuffer]; 1337*8975f5c5SAndroid Build Coastguard Worker 1338*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = 1339*8975f5c5SAndroid Build Coastguard Worker contextMtl->getRenderTargetCommandEncoder(*renderTarget); 1340*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(display->getUtils().clearWithDraw(context, encoder, overrideClearOps)); 1341*8975f5c5SAndroid Build Coastguard Worker } 1342*8975f5c5SAndroid Build Coastguard Worker 1343*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1344*8975f5c5SAndroid Build Coastguard Worker} 1345*8975f5c5SAndroid Build Coastguard Worker 1346*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::clearImpl(const gl::Context *context, 1347*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask clearColorBuffers, 1348*8975f5c5SAndroid Build Coastguard Worker mtl::ClearRectParams *pClearOpts) 1349*8975f5c5SAndroid Build Coastguard Worker{ 1350*8975f5c5SAndroid Build Coastguard Worker auto &clearOpts = *pClearOpts; 1351*8975f5c5SAndroid Build Coastguard Worker 1352*8975f5c5SAndroid Build Coastguard Worker if (!clearOpts.clearColor.valid() && !clearOpts.clearDepth.valid() && 1353*8975f5c5SAndroid Build Coastguard Worker !clearOpts.clearStencil.valid()) 1354*8975f5c5SAndroid Build Coastguard Worker { 1355*8975f5c5SAndroid Build Coastguard Worker // No Op. 1356*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1357*8975f5c5SAndroid Build Coastguard Worker } 1358*8975f5c5SAndroid Build Coastguard Worker 1359*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1360*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle renderArea(0, 0, mState.getDimensions().width, 1361*8975f5c5SAndroid Build Coastguard Worker mState.getDimensions().height); 1362*8975f5c5SAndroid Build Coastguard Worker 1363*8975f5c5SAndroid Build Coastguard Worker clearOpts.colorFormat = mRenderPassFirstColorAttachmentFormat; 1364*8975f5c5SAndroid Build Coastguard Worker clearOpts.dstTextureSize = mState.getExtents(); 1365*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearArea = ClipRectToScissor(contextMtl->getState(), renderArea, false); 1366*8975f5c5SAndroid Build Coastguard Worker clearOpts.flipY = mFlipY; 1367*8975f5c5SAndroid Build Coastguard Worker 1368*8975f5c5SAndroid Build Coastguard Worker // Discard clear altogether if scissor has 0 width or height. 1369*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearArea.width == 0 || clearOpts.clearArea.height == 0) 1370*8975f5c5SAndroid Build Coastguard Worker { 1371*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1372*8975f5c5SAndroid Build Coastguard Worker } 1373*8975f5c5SAndroid Build Coastguard Worker 1374*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearWriteMaskArray = contextMtl->getWriteMaskArray(); 1375*8975f5c5SAndroid Build Coastguard Worker uint32_t stencilMask = contextMtl->getStencilMask(); 1376*8975f5c5SAndroid Build Coastguard Worker if (!contextMtl->getDepthMask()) 1377*8975f5c5SAndroid Build Coastguard Worker { 1378*8975f5c5SAndroid Build Coastguard Worker // Disable depth clearing, since depth write is disable 1379*8975f5c5SAndroid Build Coastguard Worker clearOpts.clearDepth.reset(); 1380*8975f5c5SAndroid Build Coastguard Worker } 1381*8975f5c5SAndroid Build Coastguard Worker 1382*8975f5c5SAndroid Build Coastguard Worker // Only clear enabled buffers 1383*8975f5c5SAndroid Build Coastguard Worker clearOpts.enabledBuffers = clearColorBuffers; 1384*8975f5c5SAndroid Build Coastguard Worker 1385*8975f5c5SAndroid Build Coastguard Worker bool allBuffersUnmasked = true; 1386*8975f5c5SAndroid Build Coastguard Worker for (size_t enabledBuffer : clearColorBuffers) 1387*8975f5c5SAndroid Build Coastguard Worker { 1388*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearWriteMaskArray[enabledBuffer] != MTLColorWriteMaskAll) 1389*8975f5c5SAndroid Build Coastguard Worker { 1390*8975f5c5SAndroid Build Coastguard Worker allBuffersUnmasked = false; 1391*8975f5c5SAndroid Build Coastguard Worker break; 1392*8975f5c5SAndroid Build Coastguard Worker } 1393*8975f5c5SAndroid Build Coastguard Worker } 1394*8975f5c5SAndroid Build Coastguard Worker 1395*8975f5c5SAndroid Build Coastguard Worker if (clearOpts.clearArea == renderArea && 1396*8975f5c5SAndroid Build Coastguard Worker (!clearOpts.clearColor.valid() || allBuffersUnmasked) && 1397*8975f5c5SAndroid Build Coastguard Worker (!clearOpts.clearStencil.valid() || 1398*8975f5c5SAndroid Build Coastguard Worker (stencilMask & mtl::kStencilMaskAll) == mtl::kStencilMaskAll)) 1399*8975f5c5SAndroid Build Coastguard Worker { 1400*8975f5c5SAndroid Build Coastguard Worker return clearWithLoadOp(context, clearColorBuffers, clearOpts); 1401*8975f5c5SAndroid Build Coastguard Worker } 1402*8975f5c5SAndroid Build Coastguard Worker 1403*8975f5c5SAndroid Build Coastguard Worker return clearWithDraw(context, clearColorBuffers, clearOpts); 1404*8975f5c5SAndroid Build Coastguard Worker} 1405*8975f5c5SAndroid Build Coastguard Worker 1406*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::invalidateImpl(const gl::Context *context, 1407*8975f5c5SAndroid Build Coastguard Worker size_t count, 1408*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments) 1409*8975f5c5SAndroid Build Coastguard Worker{ 1410*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1411*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask invalidateColorBuffers; 1412*8975f5c5SAndroid Build Coastguard Worker bool invalidateDepthBuffer = false; 1413*8975f5c5SAndroid Build Coastguard Worker bool invalidateStencilBuffer = false; 1414*8975f5c5SAndroid Build Coastguard Worker 1415*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) 1416*8975f5c5SAndroid Build Coastguard Worker { 1417*8975f5c5SAndroid Build Coastguard Worker const GLenum attachment = attachments[i]; 1418*8975f5c5SAndroid Build Coastguard Worker 1419*8975f5c5SAndroid Build Coastguard Worker switch (attachment) 1420*8975f5c5SAndroid Build Coastguard Worker { 1421*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH: 1422*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_ATTACHMENT: 1423*8975f5c5SAndroid Build Coastguard Worker invalidateDepthBuffer = true; 1424*8975f5c5SAndroid Build Coastguard Worker break; 1425*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL: 1426*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL_ATTACHMENT: 1427*8975f5c5SAndroid Build Coastguard Worker invalidateStencilBuffer = true; 1428*8975f5c5SAndroid Build Coastguard Worker break; 1429*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL_ATTACHMENT: 1430*8975f5c5SAndroid Build Coastguard Worker invalidateDepthBuffer = true; 1431*8975f5c5SAndroid Build Coastguard Worker invalidateStencilBuffer = true; 1432*8975f5c5SAndroid Build Coastguard Worker break; 1433*8975f5c5SAndroid Build Coastguard Worker default: 1434*8975f5c5SAndroid Build Coastguard Worker ASSERT( 1435*8975f5c5SAndroid Build Coastguard Worker (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) || 1436*8975f5c5SAndroid Build Coastguard Worker (attachment == GL_COLOR)); 1437*8975f5c5SAndroid Build Coastguard Worker 1438*8975f5c5SAndroid Build Coastguard Worker invalidateColorBuffers.set( 1439*8975f5c5SAndroid Build Coastguard Worker attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0)); 1440*8975f5c5SAndroid Build Coastguard Worker } 1441*8975f5c5SAndroid Build Coastguard Worker } 1442*8975f5c5SAndroid Build Coastguard Worker 1443*8975f5c5SAndroid Build Coastguard Worker // Set the appropriate storeOp for attachments. 1444*8975f5c5SAndroid Build Coastguard Worker // If we already start the render pass, then need to set the store action now. 1445*8975f5c5SAndroid Build Coastguard Worker bool renderPassStarted = contextMtl->hasStartedRenderPass(mRenderPassDesc); 1446*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = 1447*8975f5c5SAndroid Build Coastguard Worker renderPassStarted ? contextMtl->getRenderCommandEncoder() : nullptr; 1448*8975f5c5SAndroid Build Coastguard Worker 1449*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < mRenderPassDesc.numColorAttachments; ++i) 1450*8975f5c5SAndroid Build Coastguard Worker { 1451*8975f5c5SAndroid Build Coastguard Worker if (invalidateColorBuffers.test(i)) 1452*8975f5c5SAndroid Build Coastguard Worker { 1453*8975f5c5SAndroid Build Coastguard Worker // Some opaque formats, like RGB8, are emulated as RGBA with alpha channel initialized 1454*8975f5c5SAndroid Build Coastguard Worker // to 1.0. Invalidating such attachments may lead to random values in their alpha 1455*8975f5c5SAndroid Build Coastguard Worker // channel, so skip invalidation in this case. 1456*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *renderTarget = mColorRenderTargets[i]; 1457*8975f5c5SAndroid Build Coastguard Worker if (renderTarget && renderTarget->getTexture()) 1458*8975f5c5SAndroid Build Coastguard Worker { 1459*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &mtlFormat = renderTarget->getFormat(); 1460*8975f5c5SAndroid Build Coastguard Worker const angle::Format &intendedFormat = mtlFormat.intendedAngleFormat(); 1461*8975f5c5SAndroid Build Coastguard Worker const angle::Format &actualFormat = mtlFormat.actualAngleFormat(); 1462*8975f5c5SAndroid Build Coastguard Worker if (intendedFormat.alphaBits == 0 && actualFormat.alphaBits) 1463*8975f5c5SAndroid Build Coastguard Worker { 1464*8975f5c5SAndroid Build Coastguard Worker continue; 1465*8975f5c5SAndroid Build Coastguard Worker } 1466*8975f5c5SAndroid Build Coastguard Worker } 1467*8975f5c5SAndroid Build Coastguard Worker 1468*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassColorAttachmentDesc &colorAttachment = 1469*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.colorAttachments[i]; 1470*8975f5c5SAndroid Build Coastguard Worker colorAttachment.storeAction = MTLStoreActionDontCare; 1471*8975f5c5SAndroid Build Coastguard Worker if (renderPassStarted) 1472*8975f5c5SAndroid Build Coastguard Worker { 1473*8975f5c5SAndroid Build Coastguard Worker encoder->setColorStoreAction(MTLStoreActionDontCare, i); 1474*8975f5c5SAndroid Build Coastguard Worker } 1475*8975f5c5SAndroid Build Coastguard Worker } 1476*8975f5c5SAndroid Build Coastguard Worker } 1477*8975f5c5SAndroid Build Coastguard Worker 1478*8975f5c5SAndroid Build Coastguard Worker if (invalidateDepthBuffer && mDepthRenderTarget) 1479*8975f5c5SAndroid Build Coastguard Worker { 1480*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.depthAttachment.storeAction = MTLStoreActionDontCare; 1481*8975f5c5SAndroid Build Coastguard Worker if (renderPassStarted) 1482*8975f5c5SAndroid Build Coastguard Worker { 1483*8975f5c5SAndroid Build Coastguard Worker encoder->setDepthStoreAction(MTLStoreActionDontCare); 1484*8975f5c5SAndroid Build Coastguard Worker } 1485*8975f5c5SAndroid Build Coastguard Worker } 1486*8975f5c5SAndroid Build Coastguard Worker 1487*8975f5c5SAndroid Build Coastguard Worker if (invalidateStencilBuffer && mStencilRenderTarget) 1488*8975f5c5SAndroid Build Coastguard Worker { 1489*8975f5c5SAndroid Build Coastguard Worker mRenderPassDesc.stencilAttachment.storeAction = MTLStoreActionDontCare; 1490*8975f5c5SAndroid Build Coastguard Worker if (renderPassStarted) 1491*8975f5c5SAndroid Build Coastguard Worker { 1492*8975f5c5SAndroid Build Coastguard Worker encoder->setStencilStoreAction(MTLStoreActionDontCare); 1493*8975f5c5SAndroid Build Coastguard Worker } 1494*8975f5c5SAndroid Build Coastguard Worker } 1495*8975f5c5SAndroid Build Coastguard Worker 1496*8975f5c5SAndroid Build Coastguard Worker // Do not encode any further commands in this render pass which can affect the 1497*8975f5c5SAndroid Build Coastguard Worker // framebuffer, or their effects will be lost. 1498*8975f5c5SAndroid Build Coastguard Worker contextMtl->endEncoding(false); 1499*8975f5c5SAndroid Build Coastguard Worker // Reset discard flag. 1500*8975f5c5SAndroid Build Coastguard Worker onStartedDrawingToFrameBuffer(context); 1501*8975f5c5SAndroid Build Coastguard Worker 1502*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1503*8975f5c5SAndroid Build Coastguard Worker} 1504*8975f5c5SAndroid Build Coastguard Worker 1505*8975f5c5SAndroid Build Coastguard Workergl::Rectangle FramebufferMtl::getCorrectFlippedReadArea(const gl::Context *context, 1506*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &glArea) const 1507*8975f5c5SAndroid Build Coastguard Worker{ 1508*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl *readRT = getColorReadRenderTarget(context); 1509*8975f5c5SAndroid Build Coastguard Worker if (!readRT) 1510*8975f5c5SAndroid Build Coastguard Worker { 1511*8975f5c5SAndroid Build Coastguard Worker readRT = mDepthRenderTarget; 1512*8975f5c5SAndroid Build Coastguard Worker } 1513*8975f5c5SAndroid Build Coastguard Worker if (!readRT) 1514*8975f5c5SAndroid Build Coastguard Worker { 1515*8975f5c5SAndroid Build Coastguard Worker readRT = mStencilRenderTarget; 1516*8975f5c5SAndroid Build Coastguard Worker } 1517*8975f5c5SAndroid Build Coastguard Worker ASSERT(readRT); 1518*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle flippedArea = glArea; 1519*8975f5c5SAndroid Build Coastguard Worker if (mFlipY) 1520*8975f5c5SAndroid Build Coastguard Worker { 1521*8975f5c5SAndroid Build Coastguard Worker flippedArea.y = readRT->getTexture()->height(readRT->getLevelIndex()) - flippedArea.y - 1522*8975f5c5SAndroid Build Coastguard Worker flippedArea.height; 1523*8975f5c5SAndroid Build Coastguard Worker } 1524*8975f5c5SAndroid Build Coastguard Worker 1525*8975f5c5SAndroid Build Coastguard Worker return flippedArea; 1526*8975f5c5SAndroid Build Coastguard Worker} 1527*8975f5c5SAndroid Build Coastguard Worker 1528*8975f5c5SAndroid Build Coastguard Workernamespace 1529*8975f5c5SAndroid Build Coastguard Worker{ 1530*8975f5c5SAndroid Build Coastguard Worker 1531*8975f5c5SAndroid Build Coastguard Workerangle::Result readPixelsCopyImpl( 1532*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context, 1533*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area, 1534*8975f5c5SAndroid Build Coastguard Worker const PackPixelsParams &packPixelsParams, 1535*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *renderTarget, 1536*8975f5c5SAndroid Build Coastguard Worker const std::function<angle::Result(const gl::Rectangle ®ion, const uint8_t *&src)> &getDataFn, 1537*8975f5c5SAndroid Build Coastguard Worker uint8_t *pixels) 1538*8975f5c5SAndroid Build Coastguard Worker{ 1539*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &readFormat = renderTarget->getFormat(); 1540*8975f5c5SAndroid Build Coastguard Worker const angle::Format &readAngleFormat = readFormat.actualAngleFormat(); 1541*8975f5c5SAndroid Build Coastguard Worker 1542*8975f5c5SAndroid Build Coastguard Worker auto packPixelsRowParams = packPixelsParams; 1543*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle srcRowRegion(area.x, area.y, area.width, 1); 1544*8975f5c5SAndroid Build Coastguard Worker int bufferRowPitch = area.width * readAngleFormat.pixelBytes; 1545*8975f5c5SAndroid Build Coastguard Worker 1546*8975f5c5SAndroid Build Coastguard Worker int rowOffset = packPixelsParams.reverseRowOrder ? -1 : 1; 1547*8975f5c5SAndroid Build Coastguard Worker int startRow = packPixelsParams.reverseRowOrder ? (area.y1() - 1) : area.y; 1548*8975f5c5SAndroid Build Coastguard Worker 1549*8975f5c5SAndroid Build Coastguard Worker // Copy pixels row by row 1550*8975f5c5SAndroid Build Coastguard Worker packPixelsRowParams.area.height = 1; 1551*8975f5c5SAndroid Build Coastguard Worker packPixelsRowParams.reverseRowOrder = false; 1552*8975f5c5SAndroid Build Coastguard Worker for (int r = startRow, i = 0; i < area.height; 1553*8975f5c5SAndroid Build Coastguard Worker ++i, r += rowOffset, pixels += packPixelsRowParams.outputPitch) 1554*8975f5c5SAndroid Build Coastguard Worker { 1555*8975f5c5SAndroid Build Coastguard Worker srcRowRegion.y = r; 1556*8975f5c5SAndroid Build Coastguard Worker packPixelsRowParams.area.y = packPixelsParams.area.y + i; 1557*8975f5c5SAndroid Build Coastguard Worker 1558*8975f5c5SAndroid Build Coastguard Worker const uint8_t *src; 1559*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDataFn(srcRowRegion, src)); 1560*8975f5c5SAndroid Build Coastguard Worker PackPixels(packPixelsRowParams, readAngleFormat, bufferRowPitch, src, pixels); 1561*8975f5c5SAndroid Build Coastguard Worker } 1562*8975f5c5SAndroid Build Coastguard Worker 1563*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1564*8975f5c5SAndroid Build Coastguard Worker} 1565*8975f5c5SAndroid Build Coastguard Worker 1566*8975f5c5SAndroid Build Coastguard Worker} // namespace 1567*8975f5c5SAndroid Build Coastguard Worker 1568*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::readPixelsImpl(const gl::Context *context, 1569*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area, 1570*8975f5c5SAndroid Build Coastguard Worker const PackPixelsParams &packPixelsParams, 1571*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *renderTarget, 1572*8975f5c5SAndroid Build Coastguard Worker uint8_t *pixels) const 1573*8975f5c5SAndroid Build Coastguard Worker{ 1574*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1575*8975f5c5SAndroid Build Coastguard Worker const angle::FeaturesMtl &features = contextMtl->getDisplay()->getFeatures(); 1576*8975f5c5SAndroid Build Coastguard Worker 1577*8975f5c5SAndroid Build Coastguard Worker if (!renderTarget) 1578*8975f5c5SAndroid Build Coastguard Worker { 1579*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1580*8975f5c5SAndroid Build Coastguard Worker } 1581*8975f5c5SAndroid Build Coastguard Worker 1582*8975f5c5SAndroid Build Coastguard Worker if (packPixelsParams.packBuffer) 1583*8975f5c5SAndroid Build Coastguard Worker { 1584*8975f5c5SAndroid Build Coastguard Worker return readPixelsToPBO(context, area, packPixelsParams, renderTarget); 1585*8975f5c5SAndroid Build Coastguard Worker } 1586*8975f5c5SAndroid Build Coastguard Worker 1587*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef texture; 1588*8975f5c5SAndroid Build Coastguard Worker if (mBackbuffer) 1589*8975f5c5SAndroid Build Coastguard Worker { 1590*8975f5c5SAndroid Build Coastguard Worker // Backbuffer might have MSAA texture as render target, needs to obtain the 1591*8975f5c5SAndroid Build Coastguard Worker // resolved texture to be able to read pixels. 1592*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBackbuffer->ensureColorTextureReadyForReadPixels(context)); 1593*8975f5c5SAndroid Build Coastguard Worker texture = mBackbuffer->getColorTexture(); 1594*8975f5c5SAndroid Build Coastguard Worker } 1595*8975f5c5SAndroid Build Coastguard Worker else 1596*8975f5c5SAndroid Build Coastguard Worker { 1597*8975f5c5SAndroid Build Coastguard Worker texture = renderTarget->getTexture(); 1598*8975f5c5SAndroid Build Coastguard Worker // For non-default framebuffer, MSAA read pixels is disallowed. 1599*8975f5c5SAndroid Build Coastguard Worker if (!texture) 1600*8975f5c5SAndroid Build Coastguard Worker { 1601*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1602*8975f5c5SAndroid Build Coastguard Worker } 1603*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_CHECK(contextMtl, texture->samples() == 1, GL_INVALID_OPERATION); 1604*8975f5c5SAndroid Build Coastguard Worker } 1605*8975f5c5SAndroid Build Coastguard Worker 1606*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &readFormat = renderTarget->getFormat(); 1607*8975f5c5SAndroid Build Coastguard Worker const angle::Format &readAngleFormat = readFormat.actualAngleFormat(); 1608*8975f5c5SAndroid Build Coastguard Worker 1609*8975f5c5SAndroid Build Coastguard Worker if (features.copyIOSurfaceToNonIOSurfaceForReadOptimization.enabled && 1610*8975f5c5SAndroid Build Coastguard Worker texture->hasIOSurface() && texture->mipmapLevels() == 1 && 1611*8975f5c5SAndroid Build Coastguard Worker texture->textureType() == MTLTextureType2D) 1612*8975f5c5SAndroid Build Coastguard Worker { 1613*8975f5c5SAndroid Build Coastguard Worker // Reading a texture may be slow if it's an IOSurface because metal has to lock/unlock the 1614*8975f5c5SAndroid Build Coastguard Worker // surface, whereas copying the texture to non IOSurface texture and then reading from that 1615*8975f5c5SAndroid Build Coastguard Worker // may be fast depending on the GPU/driver. 1616*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(Copy2DTextureSlice0Level0ToTempTexture(context, texture, &texture)); 1617*8975f5c5SAndroid Build Coastguard Worker } 1618*8975f5c5SAndroid Build Coastguard Worker 1619*8975f5c5SAndroid Build Coastguard Worker if (features.copyTextureToBufferForReadOptimization.enabled) 1620*8975f5c5SAndroid Build Coastguard Worker { 1621*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef buffer; 1622*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CopyTextureSliceLevelToTempBuffer(context, texture, renderTarget->getLevelIndex(), 1623*8975f5c5SAndroid Build Coastguard Worker renderTarget->getLayerIndex(), &buffer)); 1624*8975f5c5SAndroid Build Coastguard Worker 1625*8975f5c5SAndroid Build Coastguard Worker int bufferRowPitch = 1626*8975f5c5SAndroid Build Coastguard Worker texture->width(renderTarget->getLevelIndex()) * readAngleFormat.pixelBytes; 1627*8975f5c5SAndroid Build Coastguard Worker 1628*8975f5c5SAndroid Build Coastguard Worker buffer->syncContent(contextMtl, contextMtl->getBlitCommandEncoder()); 1629*8975f5c5SAndroid Build Coastguard Worker const uint8_t *bufferData = buffer->mapReadOnly(contextMtl); 1630*8975f5c5SAndroid Build Coastguard Worker 1631*8975f5c5SAndroid Build Coastguard Worker angle::Result result = readPixelsCopyImpl( 1632*8975f5c5SAndroid Build Coastguard Worker context, area, packPixelsParams, renderTarget, 1633*8975f5c5SAndroid Build Coastguard Worker [&](const gl::Rectangle ®ion, const uint8_t *&src) { 1634*8975f5c5SAndroid Build Coastguard Worker src = 1635*8975f5c5SAndroid Build Coastguard Worker bufferData + region.y * bufferRowPitch + region.x * readAngleFormat.pixelBytes; 1636*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1637*8975f5c5SAndroid Build Coastguard Worker }, 1638*8975f5c5SAndroid Build Coastguard Worker pixels); 1639*8975f5c5SAndroid Build Coastguard Worker 1640*8975f5c5SAndroid Build Coastguard Worker buffer->unmap(contextMtl); 1641*8975f5c5SAndroid Build Coastguard Worker 1642*8975f5c5SAndroid Build Coastguard Worker return result; 1643*8975f5c5SAndroid Build Coastguard Worker } 1644*8975f5c5SAndroid Build Coastguard Worker 1645*8975f5c5SAndroid Build Coastguard Worker if (texture->isBeingUsedByGPU(contextMtl)) 1646*8975f5c5SAndroid Build Coastguard Worker { 1647*8975f5c5SAndroid Build Coastguard Worker contextMtl->flushCommandBuffer(mtl::WaitUntilFinished); 1648*8975f5c5SAndroid Build Coastguard Worker } 1649*8975f5c5SAndroid Build Coastguard Worker 1650*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer readPixelRowBuffer; 1651*8975f5c5SAndroid Build Coastguard Worker int bufferRowPitch = area.width * readAngleFormat.pixelBytes; 1652*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_ALLOC(contextMtl, readPixelRowBuffer.resize(bufferRowPitch)); 1653*8975f5c5SAndroid Build Coastguard Worker return readPixelsCopyImpl( 1654*8975f5c5SAndroid Build Coastguard Worker context, area, packPixelsParams, renderTarget, 1655*8975f5c5SAndroid Build Coastguard Worker [&](const gl::Rectangle ®ion, const uint8_t *&src) { 1656*8975f5c5SAndroid Build Coastguard Worker // Read the pixels data to the row buffer 1657*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::ReadTexturePerSliceBytes( 1658*8975f5c5SAndroid Build Coastguard Worker context, texture, bufferRowPitch, region, renderTarget->getLevelIndex(), 1659*8975f5c5SAndroid Build Coastguard Worker renderTarget->getLayerIndex(), readPixelRowBuffer.data())); 1660*8975f5c5SAndroid Build Coastguard Worker src = readPixelRowBuffer.data(); 1661*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1662*8975f5c5SAndroid Build Coastguard Worker }, 1663*8975f5c5SAndroid Build Coastguard Worker pixels); 1664*8975f5c5SAndroid Build Coastguard Worker} 1665*8975f5c5SAndroid Build Coastguard Worker 1666*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::readPixelsToPBO(const gl::Context *context, 1667*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area, 1668*8975f5c5SAndroid Build Coastguard Worker const PackPixelsParams &packPixelsParams, 1669*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *renderTarget) const 1670*8975f5c5SAndroid Build Coastguard Worker{ 1671*8975f5c5SAndroid Build Coastguard Worker ASSERT(packPixelsParams.packBuffer); 1672*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderTarget); 1673*8975f5c5SAndroid Build Coastguard Worker 1674*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1675*8975f5c5SAndroid Build Coastguard Worker 1676*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_CHECK(contextMtl, packPixelsParams.offset <= std::numeric_limits<uint32_t>::max(), 1677*8975f5c5SAndroid Build Coastguard Worker GL_INVALID_OPERATION); 1678*8975f5c5SAndroid Build Coastguard Worker uint32_t offset = static_cast<uint32_t>(packPixelsParams.offset); 1679*8975f5c5SAndroid Build Coastguard Worker 1680*8975f5c5SAndroid Build Coastguard Worker BufferMtl *packBufferMtl = mtl::GetImpl(packPixelsParams.packBuffer); 1681*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef dstBuffer = packBufferMtl->getCurrentBuffer(); 1682*8975f5c5SAndroid Build Coastguard Worker 1683*8975f5c5SAndroid Build Coastguard Worker return readPixelsToBuffer(context, area, renderTarget, packPixelsParams.reverseRowOrder, 1684*8975f5c5SAndroid Build Coastguard Worker *packPixelsParams.destFormat, offset, packPixelsParams.outputPitch, 1685*8975f5c5SAndroid Build Coastguard Worker &dstBuffer); 1686*8975f5c5SAndroid Build Coastguard Worker} 1687*8975f5c5SAndroid Build Coastguard Worker 1688*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::readPixelsToBuffer(const gl::Context *context, 1689*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &area, 1690*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *renderTarget, 1691*8975f5c5SAndroid Build Coastguard Worker bool reverseRowOrder, 1692*8975f5c5SAndroid Build Coastguard Worker const angle::Format &dstAngleFormat, 1693*8975f5c5SAndroid Build Coastguard Worker uint32_t dstBufferOffset, 1694*8975f5c5SAndroid Build Coastguard Worker uint32_t dstBufferRowPitch, 1695*8975f5c5SAndroid Build Coastguard Worker const mtl::BufferRef *pDstBuffer) const 1696*8975f5c5SAndroid Build Coastguard Worker{ 1697*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderTarget); 1698*8975f5c5SAndroid Build Coastguard Worker 1699*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1700*8975f5c5SAndroid Build Coastguard Worker 1701*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &readFormat = renderTarget->getFormat(); 1702*8975f5c5SAndroid Build Coastguard Worker const angle::Format &readAngleFormat = readFormat.actualAngleFormat(); 1703*8975f5c5SAndroid Build Coastguard Worker 1704*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef texture = renderTarget->getTexture(); 1705*8975f5c5SAndroid Build Coastguard Worker 1706*8975f5c5SAndroid Build Coastguard Worker const mtl::BufferRef &dstBuffer = *pDstBuffer; 1707*8975f5c5SAndroid Build Coastguard Worker 1708*8975f5c5SAndroid Build Coastguard Worker if (dstAngleFormat.id != readAngleFormat.id || texture->samples() > 1 || 1709*8975f5c5SAndroid Build Coastguard Worker (dstBufferOffset % dstAngleFormat.pixelBytes) || 1710*8975f5c5SAndroid Build Coastguard Worker (dstBufferOffset % mtl::kTextureToBufferBlittingAlignment) || 1711*8975f5c5SAndroid Build Coastguard Worker (dstBufferRowPitch < area.width * dstAngleFormat.pixelBytes)) 1712*8975f5c5SAndroid Build Coastguard Worker { 1713*8975f5c5SAndroid Build Coastguard Worker const angle::Format *actualDstAngleFormat; 1714*8975f5c5SAndroid Build Coastguard Worker 1715*8975f5c5SAndroid Build Coastguard Worker // SRGB is special case: We need to write sRGB values to buffer, not linear values. 1716*8975f5c5SAndroid Build Coastguard Worker switch (readAngleFormat.id) 1717*8975f5c5SAndroid Build Coastguard Worker { 1718*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::B8G8R8A8_UNORM_SRGB: 1719*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8_UNORM_SRGB: 1720*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UNORM_SRGB: 1721*8975f5c5SAndroid Build Coastguard Worker if (dstAngleFormat.id != readAngleFormat.id) 1722*8975f5c5SAndroid Build Coastguard Worker { 1723*8975f5c5SAndroid Build Coastguard Worker switch (dstAngleFormat.id) 1724*8975f5c5SAndroid Build Coastguard Worker { 1725*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::B8G8R8A8_UNORM: 1726*8975f5c5SAndroid Build Coastguard Worker actualDstAngleFormat = 1727*8975f5c5SAndroid Build Coastguard Worker &angle::Format::Get(angle::FormatID::B8G8R8A8_UNORM_SRGB); 1728*8975f5c5SAndroid Build Coastguard Worker break; 1729*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UNORM: 1730*8975f5c5SAndroid Build Coastguard Worker actualDstAngleFormat = 1731*8975f5c5SAndroid Build Coastguard Worker &angle::Format::Get(angle::FormatID::R8G8B8A8_UNORM_SRGB); 1732*8975f5c5SAndroid Build Coastguard Worker break; 1733*8975f5c5SAndroid Build Coastguard Worker default: 1734*8975f5c5SAndroid Build Coastguard Worker // Unsupported format. 1735*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_CHECK(contextMtl, false, GL_INVALID_ENUM); 1736*8975f5c5SAndroid Build Coastguard Worker } 1737*8975f5c5SAndroid Build Coastguard Worker break; 1738*8975f5c5SAndroid Build Coastguard Worker } 1739*8975f5c5SAndroid Build Coastguard Worker OS_FALLTHROUGH; 1740*8975f5c5SAndroid Build Coastguard Worker default: 1741*8975f5c5SAndroid Build Coastguard Worker actualDstAngleFormat = &dstAngleFormat; 1742*8975f5c5SAndroid Build Coastguard Worker } 1743*8975f5c5SAndroid Build Coastguard Worker 1744*8975f5c5SAndroid Build Coastguard Worker // Use compute shader 1745*8975f5c5SAndroid Build Coastguard Worker mtl::CopyPixelsToBufferParams params; 1746*8975f5c5SAndroid Build Coastguard Worker params.buffer = dstBuffer; 1747*8975f5c5SAndroid Build Coastguard Worker params.bufferStartOffset = dstBufferOffset; 1748*8975f5c5SAndroid Build Coastguard Worker params.bufferRowPitch = dstBufferRowPitch; 1749*8975f5c5SAndroid Build Coastguard Worker 1750*8975f5c5SAndroid Build Coastguard Worker params.texture = texture; 1751*8975f5c5SAndroid Build Coastguard Worker params.textureArea = area; 1752*8975f5c5SAndroid Build Coastguard Worker params.textureLevel = renderTarget->getLevelIndex(); 1753*8975f5c5SAndroid Build Coastguard Worker params.textureSliceOrDeph = renderTarget->getLayerIndex(); 1754*8975f5c5SAndroid Build Coastguard Worker params.reverseTextureRowOrder = reverseRowOrder; 1755*8975f5c5SAndroid Build Coastguard Worker 1756*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().packPixelsFromTextureToBuffer( 1757*8975f5c5SAndroid Build Coastguard Worker contextMtl, *actualDstAngleFormat, params)); 1758*8975f5c5SAndroid Build Coastguard Worker } 1759*8975f5c5SAndroid Build Coastguard Worker else 1760*8975f5c5SAndroid Build Coastguard Worker { 1761*8975f5c5SAndroid Build Coastguard Worker // Use blit command encoder 1762*8975f5c5SAndroid Build Coastguard Worker if (!reverseRowOrder) 1763*8975f5c5SAndroid Build Coastguard Worker { 1764*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::ReadTexturePerSliceBytesToBuffer( 1765*8975f5c5SAndroid Build Coastguard Worker context, texture, dstBufferRowPitch, area, renderTarget->getLevelIndex(), 1766*8975f5c5SAndroid Build Coastguard Worker renderTarget->getLayerIndex(), dstBufferOffset, dstBuffer)); 1767*8975f5c5SAndroid Build Coastguard Worker } 1768*8975f5c5SAndroid Build Coastguard Worker else 1769*8975f5c5SAndroid Build Coastguard Worker { 1770*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle srcRowRegion(area.x, area.y, area.width, 1); 1771*8975f5c5SAndroid Build Coastguard Worker 1772*8975f5c5SAndroid Build Coastguard Worker int startRow = area.y1() - 1; 1773*8975f5c5SAndroid Build Coastguard Worker 1774*8975f5c5SAndroid Build Coastguard Worker uint32_t bufferRowOffset = dstBufferOffset; 1775*8975f5c5SAndroid Build Coastguard Worker // Copy pixels row by row 1776*8975f5c5SAndroid Build Coastguard Worker for (int r = startRow, copiedRows = 0; copiedRows < area.height; 1777*8975f5c5SAndroid Build Coastguard Worker ++copiedRows, --r, bufferRowOffset += dstBufferRowPitch) 1778*8975f5c5SAndroid Build Coastguard Worker { 1779*8975f5c5SAndroid Build Coastguard Worker srcRowRegion.y = r; 1780*8975f5c5SAndroid Build Coastguard Worker 1781*8975f5c5SAndroid Build Coastguard Worker // Read the pixels data to the buffer's row 1782*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::ReadTexturePerSliceBytesToBuffer( 1783*8975f5c5SAndroid Build Coastguard Worker context, texture, dstBufferRowPitch, srcRowRegion, 1784*8975f5c5SAndroid Build Coastguard Worker renderTarget->getLevelIndex(), renderTarget->getLayerIndex(), bufferRowOffset, 1785*8975f5c5SAndroid Build Coastguard Worker dstBuffer)); 1786*8975f5c5SAndroid Build Coastguard Worker } 1787*8975f5c5SAndroid Build Coastguard Worker } 1788*8975f5c5SAndroid Build Coastguard Worker } 1789*8975f5c5SAndroid Build Coastguard Worker 1790*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1791*8975f5c5SAndroid Build Coastguard Worker} 1792*8975f5c5SAndroid Build Coastguard Worker 1793*8975f5c5SAndroid Build Coastguard Workerangle::Result FramebufferMtl::unresolveIfNeeded(const gl::Context *context, 1794*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder) 1795*8975f5c5SAndroid Build Coastguard Worker{ 1796*8975f5c5SAndroid Build Coastguard Worker ContextMtl *contextMtl = mtl::GetImpl(context); 1797*8975f5c5SAndroid Build Coastguard Worker DisplayMtl *display = contextMtl->getDisplay(); 1798*8975f5c5SAndroid Build Coastguard Worker 1799*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassDesc &renderPassDesc = encoder->renderPassDesc(); 1800*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle renderArea = this->getCompleteRenderArea(); 1801*8975f5c5SAndroid Build Coastguard Worker 1802*8975f5c5SAndroid Build Coastguard Worker mtl::BlitParams baseParams; 1803*8975f5c5SAndroid Build Coastguard Worker baseParams.dstTextureSize = gl::Extents(renderArea.width, renderArea.height, 1); 1804*8975f5c5SAndroid Build Coastguard Worker baseParams.dstRect = renderArea; 1805*8975f5c5SAndroid Build Coastguard Worker baseParams.dstScissorRect = renderArea; 1806*8975f5c5SAndroid Build Coastguard Worker baseParams.dstFlipY = false; 1807*8975f5c5SAndroid Build Coastguard Worker 1808*8975f5c5SAndroid Build Coastguard Worker baseParams.srcNormalizedCoords = 1809*8975f5c5SAndroid Build Coastguard Worker mtl::NormalizedCoords(0, 0, renderArea.width, renderArea.height, renderArea); 1810*8975f5c5SAndroid Build Coastguard Worker 1811*8975f5c5SAndroid Build Coastguard Worker baseParams.srcYFlipped = false; 1812*8975f5c5SAndroid Build Coastguard Worker baseParams.unpackFlipX = false; 1813*8975f5c5SAndroid Build Coastguard Worker baseParams.unpackFlipY = false; 1814*8975f5c5SAndroid Build Coastguard Worker 1815*8975f5c5SAndroid Build Coastguard Worker // Unresolve any color attachment if the intended loadAction = MTLLoadActionLoad and the 1816*8975f5c5SAndroid Build Coastguard Worker // respective MS texture is memoryless. 1817*8975f5c5SAndroid Build Coastguard Worker mtl::ColorBlitParams colorBlitParams; 1818*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.BlitParams::operator=(baseParams); 1819*8975f5c5SAndroid Build Coastguard Worker for (uint32_t colorIndexGL = 0; colorIndexGL < renderPassDesc.numColorAttachments; 1820*8975f5c5SAndroid Build Coastguard Worker ++colorIndexGL) 1821*8975f5c5SAndroid Build Coastguard Worker { 1822*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassColorAttachmentDesc &colorAttachment = 1823*8975f5c5SAndroid Build Coastguard Worker renderPassDesc.colorAttachments[colorIndexGL]; 1824*8975f5c5SAndroid Build Coastguard Worker 1825*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.loadAction != MTLLoadActionLoad || 1826*8975f5c5SAndroid Build Coastguard Worker !colorAttachment.hasImplicitMSTexture() || 1827*8975f5c5SAndroid Build Coastguard Worker !colorAttachment.implicitMSTexture->shouldNotLoadStore()) 1828*8975f5c5SAndroid Build Coastguard Worker { 1829*8975f5c5SAndroid Build Coastguard Worker continue; 1830*8975f5c5SAndroid Build Coastguard Worker } 1831*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl *colorRenderTarget = mColorRenderTargets[colorIndexGL]; 1832*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = colorRenderTarget->getFormat().actualAngleFormat(); 1833*8975f5c5SAndroid Build Coastguard Worker 1834*8975f5c5SAndroid Build Coastguard Worker // Blit the resolve texture to the MS texture. 1835*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.src = colorAttachment.texture; 1836*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.srcLevel = colorAttachment.level; 1837*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.srcLayer = colorAttachment.sliceOrDepth; 1838*8975f5c5SAndroid Build Coastguard Worker 1839*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.enabledBuffers.reset(); 1840*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.enabledBuffers.set(colorIndexGL); 1841*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.filter = GL_NEAREST; 1842*8975f5c5SAndroid Build Coastguard Worker colorBlitParams.dstLuminance = angleFormat.isLUMA(); 1843*8975f5c5SAndroid Build Coastguard Worker 1844*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 1845*8975f5c5SAndroid Build Coastguard Worker display->getUtils().blitColorWithDraw(context, encoder, angleFormat, colorBlitParams)); 1846*8975f5c5SAndroid Build Coastguard Worker } 1847*8975f5c5SAndroid Build Coastguard Worker 1848*8975f5c5SAndroid Build Coastguard Worker // Similarly, unresolve depth/stencil attachments. 1849*8975f5c5SAndroid Build Coastguard Worker mtl::DepthStencilBlitParams dsBlitParams; 1850*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.BlitParams::operator=(baseParams); 1851*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassDepthAttachmentDesc &depthAttachment = renderPassDesc.depthAttachment; 1852*8975f5c5SAndroid Build Coastguard Worker if (depthAttachment.loadAction == MTLLoadActionLoad && depthAttachment.hasImplicitMSTexture() && 1853*8975f5c5SAndroid Build Coastguard Worker depthAttachment.implicitMSTexture->shouldNotLoadStore()) 1854*8975f5c5SAndroid Build Coastguard Worker { 1855*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.src = depthAttachment.texture; 1856*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLevel = depthAttachment.level; 1857*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLayer = depthAttachment.sliceOrDepth; 1858*8975f5c5SAndroid Build Coastguard Worker } 1859*8975f5c5SAndroid Build Coastguard Worker 1860*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassStencilAttachmentDesc &stencilAttachment = 1861*8975f5c5SAndroid Build Coastguard Worker renderPassDesc.stencilAttachment; 1862*8975f5c5SAndroid Build Coastguard Worker if (stencilAttachment.loadAction == MTLLoadActionLoad && 1863*8975f5c5SAndroid Build Coastguard Worker stencilAttachment.hasImplicitMSTexture() && 1864*8975f5c5SAndroid Build Coastguard Worker stencilAttachment.implicitMSTexture->shouldNotLoadStore()) 1865*8975f5c5SAndroid Build Coastguard Worker { 1866*8975f5c5SAndroid Build Coastguard Worker if (mState.hasSeparateDepthAndStencilAttachments()) 1867*8975f5c5SAndroid Build Coastguard Worker { 1868*8975f5c5SAndroid Build Coastguard Worker // Blit depth/stencil separately. 1869*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitDepthStencilWithDraw( 1870*8975f5c5SAndroid Build Coastguard Worker context, encoder, dsBlitParams)); 1871*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.src = nullptr; 1872*8975f5c5SAndroid Build Coastguard Worker } 1873*8975f5c5SAndroid Build Coastguard Worker 1874*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcStencil = stencilAttachment.texture->getStencilView(); 1875*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLevel = stencilAttachment.level; 1876*8975f5c5SAndroid Build Coastguard Worker dsBlitParams.srcLayer = stencilAttachment.sliceOrDepth; 1877*8975f5c5SAndroid Build Coastguard Worker } 1878*8975f5c5SAndroid Build Coastguard Worker 1879*8975f5c5SAndroid Build Coastguard Worker if (dsBlitParams.src || dsBlitParams.srcStencil) 1880*8975f5c5SAndroid Build Coastguard Worker { 1881*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitDepthStencilWithDraw(context, encoder, 1882*8975f5c5SAndroid Build Coastguard Worker dsBlitParams)); 1883*8975f5c5SAndroid Build Coastguard Worker } 1884*8975f5c5SAndroid Build Coastguard Worker 1885*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1886*8975f5c5SAndroid Build Coastguard Worker} 1887*8975f5c5SAndroid Build Coastguard Worker 1888*8975f5c5SAndroid Build Coastguard Worker} // namespace rx 1889