1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlOpsRenderPass.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/GrBackendUtils.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrColor.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 13cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlCommandBuffer.h" 14cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlPipelineState.h" 15cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlPipelineStateBuilder.h" 16cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlRenderCommandEncoder.h" 17cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlRenderTarget.h" 18cb93a386Sopenharmony_ci#include "src/gpu/mtl/GrMtlTexture.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci#if !__has_feature(objc_arc) 21cb93a386Sopenharmony_ci#error This file must be compiled with Arc. Use -fobjc-arc flag 22cb93a386Sopenharmony_ci#endif 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciGR_NORETAIN_BEGIN 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciGrMtlOpsRenderPass::GrMtlOpsRenderPass(GrMtlGpu* gpu, GrRenderTarget* rt, 27cb93a386Sopenharmony_ci sk_sp<GrMtlFramebuffer> framebuffer, GrSurfaceOrigin origin, 28cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, 29cb93a386Sopenharmony_ci const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo) 30cb93a386Sopenharmony_ci : INHERITED(rt, origin) 31cb93a386Sopenharmony_ci , fGpu(gpu) 32cb93a386Sopenharmony_ci , fFramebuffer(std::move(framebuffer)) { 33cb93a386Sopenharmony_ci this->setupRenderPass(colorInfo, stencilInfo); 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciGrMtlOpsRenderPass::~GrMtlOpsRenderPass() { 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::submit() { 40cb93a386Sopenharmony_ci if (!fFramebuffer) { 41cb93a386Sopenharmony_ci return; 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci SkIRect iBounds; 44cb93a386Sopenharmony_ci fBounds.roundOut(&iBounds); 45cb93a386Sopenharmony_ci fGpu->submitIndirectCommandBuffer(fRenderTarget, fOrigin, &iBounds); 46cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = nil; 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_cistatic MTLPrimitiveType gr_to_mtl_primitive(GrPrimitiveType primitiveType) { 50cb93a386Sopenharmony_ci const static MTLPrimitiveType mtlPrimitiveType[] { 51cb93a386Sopenharmony_ci MTLPrimitiveTypeTriangle, 52cb93a386Sopenharmony_ci MTLPrimitiveTypeTriangleStrip, 53cb93a386Sopenharmony_ci MTLPrimitiveTypePoint, 54cb93a386Sopenharmony_ci MTLPrimitiveTypeLine, 55cb93a386Sopenharmony_ci MTLPrimitiveTypeLineStrip 56cb93a386Sopenharmony_ci }; 57cb93a386Sopenharmony_ci static_assert((int)GrPrimitiveType::kTriangles == 0); 58cb93a386Sopenharmony_ci static_assert((int)GrPrimitiveType::kTriangleStrip == 1); 59cb93a386Sopenharmony_ci static_assert((int)GrPrimitiveType::kPoints == 2); 60cb93a386Sopenharmony_ci static_assert((int)GrPrimitiveType::kLines == 3); 61cb93a386Sopenharmony_ci static_assert((int)GrPrimitiveType::kLineStrip == 4); 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci SkASSERT(primitiveType <= GrPrimitiveType::kLineStrip); 64cb93a386Sopenharmony_ci return mtlPrimitiveType[static_cast<int>(primitiveType)]; 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cibool GrMtlOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo, 68cb93a386Sopenharmony_ci const SkRect& drawBounds) { 69cb93a386Sopenharmony_ci const GrMtlCaps& caps = fGpu->mtlCaps(); 70cb93a386Sopenharmony_ci GrProgramDesc programDesc = caps.makeDesc(fRenderTarget, programInfo, 71cb93a386Sopenharmony_ci GrCaps::ProgramDescOverrideFlags::kNone); 72cb93a386Sopenharmony_ci if (!programDesc.isValid()) { 73cb93a386Sopenharmony_ci return false; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci fActivePipelineState = fGpu->resourceProvider().findOrCreateCompatiblePipelineState( 77cb93a386Sopenharmony_ci programDesc, programInfo); 78cb93a386Sopenharmony_ci if (!fActivePipelineState) { 79cb93a386Sopenharmony_ci return false; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci fActivePipelineState->setData(fFramebuffer.get(), programInfo); 83cb93a386Sopenharmony_ci fCurrentVertexStride = programInfo.geomProc().vertexStride(); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci if (!fActiveRenderCmdEncoder) { 86cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = 87cb93a386Sopenharmony_ci fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, 88cb93a386Sopenharmony_ci fActivePipelineState, this); 89cb93a386Sopenharmony_ci if (!fActiveRenderCmdEncoder) { 90cb93a386Sopenharmony_ci return false; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci fGpu->commandBuffer()->addGrSurface( 93cb93a386Sopenharmony_ci sk_ref_sp<GrMtlAttachment>(fFramebuffer->colorAttachment())); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->setRenderPipelineState( 97cb93a386Sopenharmony_ci fActivePipelineState->pipeline()->mtlPipelineState()); 98cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 99cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 100cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 101cb93a386Sopenharmony_ci fDebugGroupActive = true; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci#endif 104cb93a386Sopenharmony_ci fActivePipelineState->setDrawState(fActiveRenderCmdEncoder, 105cb93a386Sopenharmony_ci programInfo.pipeline().writeSwizzle(), 106cb93a386Sopenharmony_ci programInfo.pipeline().getXferProcessor()); 107cb93a386Sopenharmony_ci if (this->gpu()->caps()->wireframeMode() || programInfo.pipeline().isWireframe()) { 108cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->setTriangleFillMode(MTLTriangleFillModeLines); 109cb93a386Sopenharmony_ci } else { 110cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->setTriangleFillMode(MTLTriangleFillModeFill); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci if (!programInfo.pipeline().isScissorTestEnabled()) { 114cb93a386Sopenharmony_ci // "Disable" scissor by setting it to the full pipeline bounds. 115cb93a386Sopenharmony_ci SkISize dimensions = fFramebuffer->colorAttachment()->dimensions(); 116cb93a386Sopenharmony_ci GrMtlPipelineState::SetDynamicScissorRectState(fActiveRenderCmdEncoder, 117cb93a386Sopenharmony_ci dimensions, fOrigin, 118cb93a386Sopenharmony_ci SkIRect::MakeWH(dimensions.width(), 119cb93a386Sopenharmony_ci dimensions.height())); 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci fActivePrimitiveType = gr_to_mtl_primitive(programInfo.primitiveType()); 123cb93a386Sopenharmony_ci fBounds.join(drawBounds); 124cb93a386Sopenharmony_ci return true; 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onSetScissorRect(const SkIRect& scissor) { 128cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 129cb93a386Sopenharmony_ci SkASSERT(fActiveRenderCmdEncoder); 130cb93a386Sopenharmony_ci GrMtlPipelineState::SetDynamicScissorRectState(fActiveRenderCmdEncoder, 131cb93a386Sopenharmony_ci fFramebuffer->colorAttachment()->dimensions(), 132cb93a386Sopenharmony_ci fOrigin, scissor); 133cb93a386Sopenharmony_ci} 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_cibool GrMtlOpsRenderPass::onBindTextures(const GrGeometryProcessor& geomProc, 136cb93a386Sopenharmony_ci const GrSurfaceProxy* const geomProcTextures[], 137cb93a386Sopenharmony_ci const GrPipeline& pipeline) { 138cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 139cb93a386Sopenharmony_ci SkASSERT(fActiveRenderCmdEncoder); 140cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 141cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 142cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 143cb93a386Sopenharmony_ci fDebugGroupActive = true; 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci#endif 146cb93a386Sopenharmony_ci fActivePipelineState->setTextures(geomProc, pipeline, geomProcTextures); 147cb93a386Sopenharmony_ci fActivePipelineState->bindTextures(fActiveRenderCmdEncoder); 148cb93a386Sopenharmony_ci return true; 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float, 4> color) { 152cb93a386Sopenharmony_ci // Partial clears are not supported 153cb93a386Sopenharmony_ci SkASSERT(!scissor.enabled()); 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci // Ideally we should never end up here since all clears should either be done as draws or 156cb93a386Sopenharmony_ci // load ops in metal. However, if a client inserts a wait op we need to handle it. 157cb93a386Sopenharmony_ci auto colorAttachment = fRenderPassDesc.colorAttachments[0]; 158cb93a386Sopenharmony_ci colorAttachment.clearColor = MTLClearColorMake(color[0], color[1], color[2], color[3]); 159cb93a386Sopenharmony_ci colorAttachment.loadAction = MTLLoadActionClear; 160cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = 161cb93a386Sopenharmony_ci fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this); 162cb93a386Sopenharmony_ci} 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { 165cb93a386Sopenharmony_ci // Partial clears are not supported 166cb93a386Sopenharmony_ci SkASSERT(!scissor.enabled()); 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci GrAttachment* sb = fFramebuffer->stencilAttachment(); 169cb93a386Sopenharmony_ci // this should only be called internally when we know we have a 170cb93a386Sopenharmony_ci // stencil buffer. 171cb93a386Sopenharmony_ci SkASSERT(sb); 172cb93a386Sopenharmony_ci int stencilBitCount = GrBackendFormatStencilBits(sb->backendFormat()); 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci // The contract with the callers does not guarantee that we preserve all bits in the stencil 175cb93a386Sopenharmony_ci // during this clear. Thus we will clear the entire stencil to the desired value. 176cb93a386Sopenharmony_ci auto stencilAttachment = fRenderPassDesc.stencilAttachment; 177cb93a386Sopenharmony_ci if (insideStencilMask) { 178cb93a386Sopenharmony_ci stencilAttachment.clearStencil = (1 << (stencilBitCount - 1)); 179cb93a386Sopenharmony_ci } else { 180cb93a386Sopenharmony_ci stencilAttachment.clearStencil = 0; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci stencilAttachment.loadAction = MTLLoadActionClear; 184cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = this->setupResolve(); 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci if (!fActiveRenderCmdEncoder) { 187cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = 188cb93a386Sopenharmony_ci fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this); 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci} 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) { 193cb93a386Sopenharmony_ci // TODO: could this be more efficient? 194cb93a386Sopenharmony_ci state->doUpload(upload); 195cb93a386Sopenharmony_ci // doUpload() creates a blitCommandEncoder, so if we had a previous render we need to 196cb93a386Sopenharmony_ci // adjust the renderPassDescriptor to load from it. 197cb93a386Sopenharmony_ci if (fActiveRenderCmdEncoder) { 198cb93a386Sopenharmony_ci auto colorAttachment = fRenderPassDesc.colorAttachments[0]; 199cb93a386Sopenharmony_ci colorAttachment.loadAction = MTLLoadActionLoad; 200cb93a386Sopenharmony_ci auto mtlStencil = fRenderPassDesc.stencilAttachment; 201cb93a386Sopenharmony_ci mtlStencil.loadAction = MTLLoadActionLoad; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci // If the previous renderCommandEncoder did a resolve without an MSAA store 204cb93a386Sopenharmony_ci // (e.g., if the color attachment is memoryless) we need to copy the contents of 205cb93a386Sopenharmony_ci // the resolve attachment to the MSAA attachment at this point. 206cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = this->setupResolve(); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci if (!fActiveRenderCmdEncoder) { 209cb93a386Sopenharmony_ci // If setting up for the resolve didn't create an encoder, it's probably reasonable to 210cb93a386Sopenharmony_ci // create a new encoder at this point, though maybe not necessary. 211cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = 212cb93a386Sopenharmony_ci fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci} 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::initRenderState(GrMtlRenderCommandEncoder* encoder) { 217cb93a386Sopenharmony_ci if (!encoder) { 218cb93a386Sopenharmony_ci return; 219cb93a386Sopenharmony_ci } 220cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 221cb93a386Sopenharmony_ci encoder->pushDebugGroup(@"initRenderState"); 222cb93a386Sopenharmony_ci#endif 223cb93a386Sopenharmony_ci encoder->setFrontFacingWinding(MTLWindingCounterClockwise); 224cb93a386Sopenharmony_ci SkISize colorAttachmentDimensions = fFramebuffer->colorAttachment()->dimensions(); 225cb93a386Sopenharmony_ci // Strictly speaking we shouldn't have to set this, as the default viewport is the size of 226cb93a386Sopenharmony_ci // the drawable used to generate the renderCommandEncoder -- but just in case. 227cb93a386Sopenharmony_ci MTLViewport viewport = { 0.0, 0.0, 228cb93a386Sopenharmony_ci (double) colorAttachmentDimensions.width(), 229cb93a386Sopenharmony_ci (double) colorAttachmentDimensions.height(), 230cb93a386Sopenharmony_ci 0.0, 1.0 }; 231cb93a386Sopenharmony_ci encoder->setViewport(viewport); 232cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 233cb93a386Sopenharmony_ci encoder->popDebugGroup(); 234cb93a386Sopenharmony_ci#endif 235cb93a386Sopenharmony_ci} 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::setupRenderPass( 238cb93a386Sopenharmony_ci const GrOpsRenderPass::LoadAndStoreInfo& colorInfo, 239cb93a386Sopenharmony_ci const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo) { 240cb93a386Sopenharmony_ci const static MTLLoadAction mtlLoadAction[] { 241cb93a386Sopenharmony_ci MTLLoadActionLoad, 242cb93a386Sopenharmony_ci MTLLoadActionClear, 243cb93a386Sopenharmony_ci MTLLoadActionDontCare 244cb93a386Sopenharmony_ci }; 245cb93a386Sopenharmony_ci static_assert((int)GrLoadOp::kLoad == 0); 246cb93a386Sopenharmony_ci static_assert((int)GrLoadOp::kClear == 1); 247cb93a386Sopenharmony_ci static_assert((int)GrLoadOp::kDiscard == 2); 248cb93a386Sopenharmony_ci SkASSERT(colorInfo.fLoadOp <= GrLoadOp::kDiscard); 249cb93a386Sopenharmony_ci SkASSERT(stencilInfo.fLoadOp <= GrLoadOp::kDiscard); 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_ci const static MTLStoreAction mtlStoreAction[] { 252cb93a386Sopenharmony_ci MTLStoreActionStore, 253cb93a386Sopenharmony_ci MTLStoreActionDontCare 254cb93a386Sopenharmony_ci }; 255cb93a386Sopenharmony_ci static_assert((int)GrStoreOp::kStore == 0); 256cb93a386Sopenharmony_ci static_assert((int)GrStoreOp::kDiscard == 1); 257cb93a386Sopenharmony_ci SkASSERT(colorInfo.fStoreOp <= GrStoreOp::kDiscard); 258cb93a386Sopenharmony_ci SkASSERT(stencilInfo.fStoreOp <= GrStoreOp::kDiscard); 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci fRenderPassDesc = [MTLRenderPassDescriptor new]; 261cb93a386Sopenharmony_ci auto colorAttachment = fRenderPassDesc.colorAttachments[0]; 262cb93a386Sopenharmony_ci auto color = fFramebuffer->colorAttachment(); 263cb93a386Sopenharmony_ci colorAttachment.texture = color->mtlTexture(); 264cb93a386Sopenharmony_ci const std::array<float, 4>& clearColor = colorInfo.fClearColor; 265cb93a386Sopenharmony_ci colorAttachment.clearColor = 266cb93a386Sopenharmony_ci MTLClearColorMake(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); 267cb93a386Sopenharmony_ci colorAttachment.loadAction = mtlLoadAction[static_cast<int>(colorInfo.fLoadOp)]; 268cb93a386Sopenharmony_ci colorAttachment.storeAction = mtlStoreAction[static_cast<int>(colorInfo.fStoreOp)]; 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci auto stencil = fFramebuffer->stencilAttachment(); 271cb93a386Sopenharmony_ci auto mtlStencil = fRenderPassDesc.stencilAttachment; 272cb93a386Sopenharmony_ci if (stencil) { 273cb93a386Sopenharmony_ci mtlStencil.texture = stencil->mtlTexture(); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci mtlStencil.clearStencil = 0; 276cb93a386Sopenharmony_ci mtlStencil.loadAction = mtlLoadAction[static_cast<int>(stencilInfo.fLoadOp)]; 277cb93a386Sopenharmony_ci mtlStencil.storeAction = mtlStoreAction[static_cast<int>(stencilInfo.fStoreOp)]; 278cb93a386Sopenharmony_ci 279cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = this->setupResolve(); 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci if (!fActiveRenderCmdEncoder) { 282cb93a386Sopenharmony_ci // Manage initial clears 283cb93a386Sopenharmony_ci if (colorInfo.fLoadOp == GrLoadOp::kClear || stencilInfo.fLoadOp == GrLoadOp::kClear) { 284cb93a386Sopenharmony_ci fBounds = SkRect::MakeWH(color->dimensions().width(), 285cb93a386Sopenharmony_ci color->dimensions().height()); 286cb93a386Sopenharmony_ci fActiveRenderCmdEncoder = 287cb93a386Sopenharmony_ci fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this); 288cb93a386Sopenharmony_ci } else { 289cb93a386Sopenharmony_ci fBounds.setEmpty(); 290cb93a386Sopenharmony_ci // For now, we lazily create the renderCommandEncoder because we may have no draws, 291cb93a386Sopenharmony_ci // and an empty renderCommandEncoder can still produce output. This can cause issues 292cb93a386Sopenharmony_ci // when we've cleared a texture upon creation -- we'll subsequently discard the contents. 293cb93a386Sopenharmony_ci // This can be removed when that ordering is fixed. 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci} 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_ciGrMtlRenderCommandEncoder* GrMtlOpsRenderPass::setupResolve() { 299cb93a386Sopenharmony_ci auto resolve = fFramebuffer->resolveAttachment(); 300cb93a386Sopenharmony_ci if (resolve) { 301cb93a386Sopenharmony_ci auto colorAttachment = fRenderPassDesc.colorAttachments[0]; 302cb93a386Sopenharmony_ci colorAttachment.resolveTexture = resolve->mtlTexture(); 303cb93a386Sopenharmony_ci // TODO: For framebufferOnly attachments we should do StoreAndMultisampleResolve if 304cb93a386Sopenharmony_ci // the storeAction is Store. But for the moment they don't take this path. 305cb93a386Sopenharmony_ci colorAttachment.storeAction = MTLStoreActionMultisampleResolve; 306cb93a386Sopenharmony_ci if (colorAttachment.loadAction == MTLLoadActionLoad) { 307cb93a386Sopenharmony_ci auto color = fFramebuffer->colorAttachment(); 308cb93a386Sopenharmony_ci auto dimensions = color->dimensions(); 309cb93a386Sopenharmony_ci // for now use the full bounds 310cb93a386Sopenharmony_ci auto nativeBounds = GrNativeRect::MakeIRectRelativeTo( 311cb93a386Sopenharmony_ci fOrigin, dimensions.height(), SkIRect::MakeSize(dimensions)); 312cb93a386Sopenharmony_ci return fGpu->loadMSAAFromResolve(color, resolve, nativeBounds, 313cb93a386Sopenharmony_ci fRenderPassDesc.stencilAttachment); 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci } 316cb93a386Sopenharmony_ci 317cb93a386Sopenharmony_ci return nullptr; 318cb93a386Sopenharmony_ci} 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onBindBuffers(sk_sp<const GrBuffer> indexBuffer, 321cb93a386Sopenharmony_ci sk_sp<const GrBuffer> instanceBuffer, 322cb93a386Sopenharmony_ci sk_sp<const GrBuffer> vertexBuffer, 323cb93a386Sopenharmony_ci GrPrimitiveRestart primRestart) { 324cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 325cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 326cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 327cb93a386Sopenharmony_ci fDebugGroupActive = true; 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci#endif 330cb93a386Sopenharmony_ci SkASSERT(GrPrimitiveRestart::kNo == primRestart); 331cb93a386Sopenharmony_ci int inputBufferIndex = 0; 332cb93a386Sopenharmony_ci if (vertexBuffer) { 333cb93a386Sopenharmony_ci SkASSERT(!vertexBuffer->isCpuBuffer()); 334cb93a386Sopenharmony_ci SkASSERT(!static_cast<const GrGpuBuffer*>(vertexBuffer.get())->isMapped()); 335cb93a386Sopenharmony_ci fActiveVertexBuffer = std::move(vertexBuffer); 336cb93a386Sopenharmony_ci fGpu->commandBuffer()->addGrBuffer(fActiveVertexBuffer); 337cb93a386Sopenharmony_ci ++inputBufferIndex; 338cb93a386Sopenharmony_ci } 339cb93a386Sopenharmony_ci if (instanceBuffer) { 340cb93a386Sopenharmony_ci SkASSERT(!instanceBuffer->isCpuBuffer()); 341cb93a386Sopenharmony_ci SkASSERT(!static_cast<const GrGpuBuffer*>(instanceBuffer.get())->isMapped()); 342cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, instanceBuffer.get(), 0, inputBufferIndex++); 343cb93a386Sopenharmony_ci fActiveInstanceBuffer = std::move(instanceBuffer); 344cb93a386Sopenharmony_ci fGpu->commandBuffer()->addGrBuffer(fActiveInstanceBuffer); 345cb93a386Sopenharmony_ci } 346cb93a386Sopenharmony_ci if (indexBuffer) { 347cb93a386Sopenharmony_ci SkASSERT(!indexBuffer->isCpuBuffer()); 348cb93a386Sopenharmony_ci SkASSERT(!static_cast<const GrGpuBuffer*>(indexBuffer.get())->isMapped()); 349cb93a386Sopenharmony_ci fActiveIndexBuffer = std::move(indexBuffer); 350cb93a386Sopenharmony_ci fGpu->commandBuffer()->addGrBuffer(fActiveIndexBuffer); 351cb93a386Sopenharmony_ci } 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDraw(int vertexCount, int baseVertex) { 355cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 356cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 357cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 358cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 359cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 360cb93a386Sopenharmony_ci fDebugGroupActive = true; 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci#endif 363cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 0, 0); 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawPrimitives(fActivePrimitiveType, baseVertex, vertexCount); 366cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 367cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 368cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 369cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 370cb93a386Sopenharmony_ci fDebugGroupActive = false; 371cb93a386Sopenharmony_ci#endif 372cb93a386Sopenharmony_ci} 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, 375cb93a386Sopenharmony_ci uint16_t maxIndexValue, int baseVertex) { 376cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 377cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 378cb93a386Sopenharmony_ci SkASSERT(fActiveIndexBuffer); 379cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 380cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 381cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 382cb93a386Sopenharmony_ci fDebugGroupActive = true; 383cb93a386Sopenharmony_ci } 384cb93a386Sopenharmony_ci#endif 385cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 386cb93a386Sopenharmony_ci fCurrentVertexStride * baseVertex, 0); 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci auto mtlIndexBuffer = static_cast<const GrMtlBuffer*>(fActiveIndexBuffer.get()); 389cb93a386Sopenharmony_ci size_t indexOffset = sizeof(uint16_t) * baseIndex; 390cb93a386Sopenharmony_ci id<MTLBuffer> indexBuffer = mtlIndexBuffer->mtlBuffer(); 391cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawIndexedPrimitives(fActivePrimitiveType, indexCount, 392cb93a386Sopenharmony_ci MTLIndexTypeUInt16, indexBuffer, indexOffset); 393cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 394cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 395cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 396cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 397cb93a386Sopenharmony_ci fDebugGroupActive = false; 398cb93a386Sopenharmony_ci#endif 399cb93a386Sopenharmony_ci} 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount, 402cb93a386Sopenharmony_ci int baseVertex) { 403cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 404cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 405cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 406cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 407cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 408cb93a386Sopenharmony_ci fDebugGroupActive = true; 409cb93a386Sopenharmony_ci } 410cb93a386Sopenharmony_ci#endif 411cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 0, 0); 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ci if (@available(macOS 10.11, iOS 9.0, *)) { 414cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawPrimitives(fActivePrimitiveType, baseVertex, vertexCount, 415cb93a386Sopenharmony_ci instanceCount, baseInstance); 416cb93a386Sopenharmony_ci } else { 417cb93a386Sopenharmony_ci SkASSERT(false); 418cb93a386Sopenharmony_ci } 419cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 420cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 421cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 422cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 423cb93a386Sopenharmony_ci fDebugGroupActive = false; 424cb93a386Sopenharmony_ci#endif 425cb93a386Sopenharmony_ci} 426cb93a386Sopenharmony_ci 427cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDrawIndexedInstanced( 428cb93a386Sopenharmony_ci int indexCount, int baseIndex, int instanceCount, int baseInstance, int baseVertex) { 429cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 430cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 431cb93a386Sopenharmony_ci SkASSERT(fActiveIndexBuffer); 432cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 433cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 434cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 435cb93a386Sopenharmony_ci fDebugGroupActive = true; 436cb93a386Sopenharmony_ci } 437cb93a386Sopenharmony_ci#endif 438cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 0, 0); 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ci auto mtlIndexBuffer = static_cast<const GrMtlBuffer*>(fActiveIndexBuffer.get()); 441cb93a386Sopenharmony_ci size_t indexOffset = sizeof(uint16_t) * baseIndex; 442cb93a386Sopenharmony_ci if (@available(macOS 10.11, iOS 9.0, *)) { 443cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawIndexedPrimitives(fActivePrimitiveType, indexCount, 444cb93a386Sopenharmony_ci MTLIndexTypeUInt16, 445cb93a386Sopenharmony_ci mtlIndexBuffer->mtlBuffer(), indexOffset, 446cb93a386Sopenharmony_ci instanceCount, baseVertex, baseInstance); 447cb93a386Sopenharmony_ci } else { 448cb93a386Sopenharmony_ci SkASSERT(false); 449cb93a386Sopenharmony_ci } 450cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 451cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 452cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 453cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 454cb93a386Sopenharmony_ci fDebugGroupActive = false; 455cb93a386Sopenharmony_ci#endif 456cb93a386Sopenharmony_ci} 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, 459cb93a386Sopenharmony_ci size_t bufferOffset, 460cb93a386Sopenharmony_ci int drawCount) { 461cb93a386Sopenharmony_ci SkASSERT(fGpu->caps()->nativeDrawIndirectSupport()); 462cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 463cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 464cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 465cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 466cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 467cb93a386Sopenharmony_ci fDebugGroupActive = true; 468cb93a386Sopenharmony_ci } 469cb93a386Sopenharmony_ci#endif 470cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 0, 0); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci auto mtlIndirectBuffer = static_cast<const GrMtlBuffer*>(drawIndirectBuffer); 473cb93a386Sopenharmony_ci const size_t stride = sizeof(GrDrawIndirectCommand); 474cb93a386Sopenharmony_ci while (drawCount >= 1) { 475cb93a386Sopenharmony_ci if (@available(macOS 10.11, iOS 9.0, *)) { 476cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawPrimitives(fActivePrimitiveType, 477cb93a386Sopenharmony_ci mtlIndirectBuffer->mtlBuffer(), bufferOffset); 478cb93a386Sopenharmony_ci } else { 479cb93a386Sopenharmony_ci SkASSERT(false); 480cb93a386Sopenharmony_ci } 481cb93a386Sopenharmony_ci drawCount--; 482cb93a386Sopenharmony_ci bufferOffset += stride; 483cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 484cb93a386Sopenharmony_ci } 485cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 486cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 487cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 488cb93a386Sopenharmony_ci fDebugGroupActive = false; 489cb93a386Sopenharmony_ci#endif 490cb93a386Sopenharmony_ci} 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, 493cb93a386Sopenharmony_ci size_t bufferOffset, 494cb93a386Sopenharmony_ci int drawCount) { 495cb93a386Sopenharmony_ci SkASSERT(fGpu->caps()->nativeDrawIndirectSupport()); 496cb93a386Sopenharmony_ci SkASSERT(fActivePipelineState); 497cb93a386Sopenharmony_ci SkASSERT(nil != fActiveRenderCmdEncoder); 498cb93a386Sopenharmony_ci SkASSERT(fActiveIndexBuffer); 499cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 500cb93a386Sopenharmony_ci if (!fDebugGroupActive) { 501cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->pushDebugGroup(@"bindAndDraw"); 502cb93a386Sopenharmony_ci fDebugGroupActive = true; 503cb93a386Sopenharmony_ci } 504cb93a386Sopenharmony_ci#endif 505cb93a386Sopenharmony_ci this->setVertexBuffer(fActiveRenderCmdEncoder, fActiveVertexBuffer.get(), 0, 0); 506cb93a386Sopenharmony_ci 507cb93a386Sopenharmony_ci auto mtlIndexBuffer = static_cast<const GrMtlBuffer*>(fActiveIndexBuffer.get()); 508cb93a386Sopenharmony_ci auto mtlIndirectBuffer = static_cast<const GrMtlBuffer*>(drawIndirectBuffer); 509cb93a386Sopenharmony_ci size_t indexOffset = 0; 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_ci const size_t stride = sizeof(GrDrawIndexedIndirectCommand); 512cb93a386Sopenharmony_ci while (drawCount >= 1) { 513cb93a386Sopenharmony_ci if (@available(macOS 10.11, iOS 9.0, *)) { 514cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->drawIndexedPrimitives(fActivePrimitiveType, 515cb93a386Sopenharmony_ci MTLIndexTypeUInt16, 516cb93a386Sopenharmony_ci mtlIndexBuffer->mtlBuffer(), 517cb93a386Sopenharmony_ci indexOffset, 518cb93a386Sopenharmony_ci mtlIndirectBuffer->mtlBuffer(), 519cb93a386Sopenharmony_ci bufferOffset); 520cb93a386Sopenharmony_ci } else { 521cb93a386Sopenharmony_ci SkASSERT(false); 522cb93a386Sopenharmony_ci } 523cb93a386Sopenharmony_ci drawCount--; 524cb93a386Sopenharmony_ci bufferOffset += stride; 525cb93a386Sopenharmony_ci fGpu->stats()->incNumDraws(); 526cb93a386Sopenharmony_ci } 527cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO 528cb93a386Sopenharmony_ci SkASSERT(fDebugGroupActive); 529cb93a386Sopenharmony_ci fActiveRenderCmdEncoder->popDebugGroup(); 530cb93a386Sopenharmony_ci fDebugGroupActive = false; 531cb93a386Sopenharmony_ci#endif 532cb93a386Sopenharmony_ci} 533cb93a386Sopenharmony_ci 534cb93a386Sopenharmony_civoid GrMtlOpsRenderPass::setVertexBuffer(GrMtlRenderCommandEncoder* encoder, 535cb93a386Sopenharmony_ci const GrBuffer* buffer, 536cb93a386Sopenharmony_ci size_t vertexOffset, 537cb93a386Sopenharmony_ci size_t inputBufferIndex) { 538cb93a386Sopenharmony_ci if (!buffer) { 539cb93a386Sopenharmony_ci return; 540cb93a386Sopenharmony_ci } 541cb93a386Sopenharmony_ci 542cb93a386Sopenharmony_ci constexpr static int kFirstBufferBindingIdx = GrMtlUniformHandler::kLastUniformBinding + 1; 543cb93a386Sopenharmony_ci int index = inputBufferIndex + kFirstBufferBindingIdx; 544cb93a386Sopenharmony_ci SkASSERT(index < 4); 545cb93a386Sopenharmony_ci auto mtlBuffer = static_cast<const GrMtlBuffer*>(buffer); 546cb93a386Sopenharmony_ci id<MTLBuffer> mtlVertexBuffer = mtlBuffer->mtlBuffer(); 547cb93a386Sopenharmony_ci SkASSERT(mtlVertexBuffer); 548cb93a386Sopenharmony_ci size_t offset = vertexOffset; 549cb93a386Sopenharmony_ci encoder->setVertexBuffer(mtlVertexBuffer, offset, index); 550cb93a386Sopenharmony_ci} 551cb93a386Sopenharmony_ci 552cb93a386Sopenharmony_ciGR_NORETAIN_END 553