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