1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
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 "experimental/graphite/src/mtl/MtlCommandBuffer.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "experimental/graphite/src/TextureProxy.h"
11cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlBlitCommandEncoder.h"
12cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlBuffer.h"
13cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlCaps.h"
14cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlGpu.h"
15cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlGraphicsPipeline.h"
16cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlRenderCommandEncoder.h"
17cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlTexture.h"
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cinamespace skgpu::mtl {
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cisk_sp<CommandBuffer> CommandBuffer::Make(const Gpu* gpu) {
22cb93a386Sopenharmony_ci    sk_cfp<id<MTLCommandBuffer>> cmdBuffer;
23cb93a386Sopenharmony_ci    id<MTLCommandQueue> queue = gpu->queue();
24cb93a386Sopenharmony_ci    if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
25cb93a386Sopenharmony_ci        sk_cfp<MTLCommandBufferDescriptor*> desc([[MTLCommandBufferDescriptor alloc] init]);
26cb93a386Sopenharmony_ci        (*desc).retainedReferences = NO;
27cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO
28cb93a386Sopenharmony_ci        (*desc).errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus;
29cb93a386Sopenharmony_ci#endif
30cb93a386Sopenharmony_ci        // We add a retain here because the command buffer is set to autorelease (not alloc or copy)
31cb93a386Sopenharmony_ci        cmdBuffer.reset([[queue commandBufferWithDescriptor:desc.get()] retain]);
32cb93a386Sopenharmony_ci    } else {
33cb93a386Sopenharmony_ci        // We add a retain here because the command buffer is set to autorelease (not alloc or copy)
34cb93a386Sopenharmony_ci        cmdBuffer.reset([[queue commandBufferWithUnretainedReferences] retain]);
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci    if (cmdBuffer == nil) {
37cb93a386Sopenharmony_ci        return nullptr;
38cb93a386Sopenharmony_ci    }
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO
41cb93a386Sopenharmony_ci     (*cmdBuffer).label = @"CommandBuffer::Make";
42cb93a386Sopenharmony_ci#endif
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    return sk_sp<CommandBuffer>(new CommandBuffer(std::move(cmdBuffer), gpu));
45cb93a386Sopenharmony_ci}
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ciCommandBuffer::CommandBuffer(sk_cfp<id<MTLCommandBuffer>> cmdBuffer, const Gpu* gpu)
48cb93a386Sopenharmony_ci    : fCommandBuffer(std::move(cmdBuffer)), fGpu(gpu) {}
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ciCommandBuffer::~CommandBuffer() {}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_cibool CommandBuffer::commit() {
53cb93a386Sopenharmony_ci    SkASSERT(!fActiveRenderCommandEncoder);
54cb93a386Sopenharmony_ci    this->endBlitCommandEncoder();
55cb93a386Sopenharmony_ci    [(*fCommandBuffer) commit];
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    // TODO: better error reporting
58cb93a386Sopenharmony_ci    if ((*fCommandBuffer).status == MTLCommandBufferStatusError) {
59cb93a386Sopenharmony_ci        NSString* description = (*fCommandBuffer).error.localizedDescription;
60cb93a386Sopenharmony_ci        const char* errorString = [description UTF8String];
61cb93a386Sopenharmony_ci        SkDebugf("Error submitting command buffer: %s\n", errorString);
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    return ((*fCommandBuffer).status != MTLCommandBufferStatusError);
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_civoid CommandBuffer::onBeginRenderPass(const RenderPassDesc& renderPassDesc) {
68cb93a386Sopenharmony_ci    SkASSERT(!fActiveRenderCommandEncoder);
69cb93a386Sopenharmony_ci    this->endBlitCommandEncoder();
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    const static MTLLoadAction mtlLoadAction[] {
72cb93a386Sopenharmony_ci        MTLLoadActionLoad,
73cb93a386Sopenharmony_ci        MTLLoadActionClear,
74cb93a386Sopenharmony_ci        MTLLoadActionDontCare
75cb93a386Sopenharmony_ci    };
76cb93a386Sopenharmony_ci    static_assert((int)LoadOp::kLoad == 0);
77cb93a386Sopenharmony_ci    static_assert((int)LoadOp::kClear == 1);
78cb93a386Sopenharmony_ci    static_assert((int)LoadOp::kDiscard == 2);
79cb93a386Sopenharmony_ci    static_assert(SK_ARRAY_COUNT(mtlLoadAction) == kLoadOpCount);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    const static MTLStoreAction mtlStoreAction[] {
82cb93a386Sopenharmony_ci        MTLStoreActionStore,
83cb93a386Sopenharmony_ci        MTLStoreActionDontCare
84cb93a386Sopenharmony_ci    };
85cb93a386Sopenharmony_ci    static_assert((int)StoreOp::kStore == 0);
86cb93a386Sopenharmony_ci    static_assert((int)StoreOp::kDiscard == 1);
87cb93a386Sopenharmony_ci    static_assert(SK_ARRAY_COUNT(mtlStoreAction) == kStoreOpCount);
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    sk_cfp<MTLRenderPassDescriptor*> descriptor([[MTLRenderPassDescriptor alloc] init]);
90cb93a386Sopenharmony_ci    // Set up color attachment.
91cb93a386Sopenharmony_ci    auto& colorInfo = renderPassDesc.fColorAttachment;
92cb93a386Sopenharmony_ci    if (colorInfo.fTextureProxy) {
93cb93a386Sopenharmony_ci        auto colorAttachment = (*descriptor).colorAttachments[0];
94cb93a386Sopenharmony_ci        const Texture* colorTexture = (const Texture*)colorInfo.fTextureProxy->texture();
95cb93a386Sopenharmony_ci        colorAttachment.texture = colorTexture->mtlTexture();
96cb93a386Sopenharmony_ci        const std::array<float, 4>& clearColor = renderPassDesc.fClearColor;
97cb93a386Sopenharmony_ci        colorAttachment.clearColor =
98cb93a386Sopenharmony_ci                MTLClearColorMake(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
99cb93a386Sopenharmony_ci        colorAttachment.loadAction = mtlLoadAction[static_cast<int>(colorInfo.fLoadOp)];
100cb93a386Sopenharmony_ci        colorAttachment.storeAction = mtlStoreAction[static_cast<int>(colorInfo.fStoreOp)];
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    // TODO:
104cb93a386Sopenharmony_ci    // * setup resolve
105cb93a386Sopenharmony_ci    // * set up stencil and depth
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder = RenderCommandEncoder::Make(fCommandBuffer.get(),
108cb93a386Sopenharmony_ci                                                             descriptor.get());
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    this->trackResource(fActiveRenderCommandEncoder);
111cb93a386Sopenharmony_ci}
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_civoid CommandBuffer::endRenderPass() {
114cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
115cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->endEncoding();
116cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder.reset();
117cb93a386Sopenharmony_ci}
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ciBlitCommandEncoder* CommandBuffer::getBlitCommandEncoder() {
120cb93a386Sopenharmony_ci    if (fActiveBlitCommandEncoder) {
121cb93a386Sopenharmony_ci        return fActiveBlitCommandEncoder.get();
122cb93a386Sopenharmony_ci    }
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    fActiveBlitCommandEncoder = BlitCommandEncoder::Make(fCommandBuffer.get());
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    if (!fActiveBlitCommandEncoder) {
127cb93a386Sopenharmony_ci        return nullptr;
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    // We add the ref on the command buffer for the BlitCommandEncoder now so that we don't need
131cb93a386Sopenharmony_ci    // to add a ref for every copy we do.
132cb93a386Sopenharmony_ci    this->trackResource(fActiveBlitCommandEncoder);
133cb93a386Sopenharmony_ci    return fActiveBlitCommandEncoder.get();
134cb93a386Sopenharmony_ci}
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_civoid CommandBuffer::endBlitCommandEncoder() {
137cb93a386Sopenharmony_ci    if (fActiveBlitCommandEncoder) {
138cb93a386Sopenharmony_ci        fActiveBlitCommandEncoder->endEncoding();
139cb93a386Sopenharmony_ci        fActiveBlitCommandEncoder.reset();
140cb93a386Sopenharmony_ci    }
141cb93a386Sopenharmony_ci}
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_civoid CommandBuffer::onBindGraphicsPipeline(const skgpu::GraphicsPipeline* graphicsPipeline) {
144cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    auto mtlPipeline = static_cast<const GraphicsPipeline*>(graphicsPipeline);
147cb93a386Sopenharmony_ci    auto pipelineState = mtlPipeline->mtlPipelineState();
148cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setRenderPipelineState(pipelineState);
149cb93a386Sopenharmony_ci    fCurrentVertexStride = mtlPipeline->vertexStride();
150cb93a386Sopenharmony_ci    fCurrentInstanceStride = mtlPipeline->instanceStride();
151cb93a386Sopenharmony_ci}
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_civoid CommandBuffer::onBindUniformBuffer(const skgpu::Buffer* uniformBuffer,
154cb93a386Sopenharmony_ci                                        size_t uniformOffset) {
155cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    id<MTLBuffer> mtlBuffer = static_cast<const Buffer*>(uniformBuffer)->mtlBuffer();
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    if (fGpu->mtlCaps().isMac()) {
160cb93a386Sopenharmony_ci        SkASSERT((uniformOffset & 0xFF) == 0);
161cb93a386Sopenharmony_ci    } else {
162cb93a386Sopenharmony_ci        SkASSERT((uniformOffset & 0xF) == 0);
163cb93a386Sopenharmony_ci    }
164cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setVertexBuffer(mtlBuffer, uniformOffset,
165cb93a386Sopenharmony_ci                                                 GraphicsPipeline::kUniformBufferIndex);
166cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setFragmentBuffer(mtlBuffer, uniformOffset,
167cb93a386Sopenharmony_ci                                                   GraphicsPipeline::kUniformBufferIndex);
168cb93a386Sopenharmony_ci}
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_civoid CommandBuffer::onBindVertexBuffers(const skgpu::Buffer* vertexBuffer,
171cb93a386Sopenharmony_ci                                        size_t vertexOffset,
172cb93a386Sopenharmony_ci                                        const skgpu::Buffer* instanceBuffer,
173cb93a386Sopenharmony_ci                                        size_t instanceOffset) {
174cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci    if (vertexBuffer) {
177cb93a386Sopenharmony_ci        id<MTLBuffer> mtlBuffer = static_cast<const Buffer*>(vertexBuffer)->mtlBuffer();
178cb93a386Sopenharmony_ci        SkASSERT((vertexOffset & 0xF) == 0);
179cb93a386Sopenharmony_ci        fActiveRenderCommandEncoder->setVertexBuffer(mtlBuffer, vertexOffset,
180cb93a386Sopenharmony_ci                                                     GraphicsPipeline::kVertexBufferIndex);
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci    if (instanceBuffer) {
183cb93a386Sopenharmony_ci        id<MTLBuffer> mtlBuffer = static_cast<const Buffer*>(instanceBuffer)->mtlBuffer();
184cb93a386Sopenharmony_ci        SkASSERT((instanceOffset & 0xF) == 0);
185cb93a386Sopenharmony_ci        fActiveRenderCommandEncoder->setVertexBuffer(mtlBuffer, instanceOffset,
186cb93a386Sopenharmony_ci                                                     GraphicsPipeline::kInstanceBufferIndex);
187cb93a386Sopenharmony_ci    }
188cb93a386Sopenharmony_ci}
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_civoid CommandBuffer::onBindIndexBuffer(const skgpu::Buffer* indexBuffer, size_t offset) {
191cb93a386Sopenharmony_ci    if (indexBuffer) {
192cb93a386Sopenharmony_ci        fCurrentIndexBuffer = static_cast<const Buffer*>(indexBuffer)->mtlBuffer();
193cb93a386Sopenharmony_ci        fCurrentIndexBufferOffset = offset;
194cb93a386Sopenharmony_ci    } else {
195cb93a386Sopenharmony_ci        fCurrentIndexBuffer = nil;
196cb93a386Sopenharmony_ci        fCurrentIndexBufferOffset = 0;
197cb93a386Sopenharmony_ci    }
198cb93a386Sopenharmony_ci}
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_cistatic MTLPrimitiveType graphite_to_mtl_primitive(PrimitiveType primitiveType) {
201cb93a386Sopenharmony_ci    const static MTLPrimitiveType mtlPrimitiveType[] {
202cb93a386Sopenharmony_ci        MTLPrimitiveTypeTriangle,
203cb93a386Sopenharmony_ci        MTLPrimitiveTypeTriangleStrip,
204cb93a386Sopenharmony_ci        MTLPrimitiveTypePoint,
205cb93a386Sopenharmony_ci    };
206cb93a386Sopenharmony_ci    static_assert((int)PrimitiveType::kTriangles == 0);
207cb93a386Sopenharmony_ci    static_assert((int)PrimitiveType::kTriangleStrip == 1);
208cb93a386Sopenharmony_ci    static_assert((int)PrimitiveType::kPoints == 2);
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci    SkASSERT(primitiveType <= PrimitiveType::kPoints);
211cb93a386Sopenharmony_ci    return mtlPrimitiveType[static_cast<int>(primitiveType)];
212cb93a386Sopenharmony_ci}
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_civoid CommandBuffer::onDraw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) {
215cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci    auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, vertexCount);
220cb93a386Sopenharmony_ci}
221cb93a386Sopenharmony_ci
222cb93a386Sopenharmony_civoid CommandBuffer::onDrawIndexed(PrimitiveType type, unsigned int baseIndex,
223cb93a386Sopenharmony_ci                                  unsigned int indexCount, unsigned int baseVertex) {
224cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci    auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setVertexBufferOffset(baseVertex * fCurrentVertexStride,
229cb93a386Sopenharmony_ci                                                       GraphicsPipeline::kVertexBufferIndex);
230cb93a386Sopenharmony_ci    size_t indexOffset =  fCurrentIndexBufferOffset + sizeof(uint16_t )* baseIndex;
231cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, indexCount,
232cb93a386Sopenharmony_ci                                                       MTLIndexTypeUInt16, fCurrentIndexBuffer,
233cb93a386Sopenharmony_ci                                                       indexOffset);
234cb93a386Sopenharmony_ci}
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_civoid CommandBuffer::onDrawInstanced(PrimitiveType type, unsigned int baseVertex,
237cb93a386Sopenharmony_ci                                    unsigned int vertexCount, unsigned int baseInstance,
238cb93a386Sopenharmony_ci                                    unsigned int instanceCount) {
239cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci    auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    // This ordering is correct
244cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, vertexCount,
245cb93a386Sopenharmony_ci                                                instanceCount, baseInstance);
246cb93a386Sopenharmony_ci}
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_civoid CommandBuffer::onDrawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
249cb93a386Sopenharmony_ci                                           unsigned int indexCount, unsigned int baseVertex,
250cb93a386Sopenharmony_ci                                           unsigned int baseInstance, unsigned int instanceCount) {
251cb93a386Sopenharmony_ci    SkASSERT(fActiveRenderCommandEncoder);
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci    auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setVertexBufferOffset(baseVertex * fCurrentVertexStride,
256cb93a386Sopenharmony_ci                                                       GraphicsPipeline::kVertexBufferIndex);
257cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->setVertexBufferOffset(baseInstance * fCurrentInstanceStride,
258cb93a386Sopenharmony_ci                                                       GraphicsPipeline::kInstanceBufferIndex);
259cb93a386Sopenharmony_ci    size_t indexOffset =  fCurrentIndexBufferOffset + sizeof(uint16_t) * baseIndex;
260cb93a386Sopenharmony_ci    fActiveRenderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, indexCount,
261cb93a386Sopenharmony_ci                                                       MTLIndexTypeUInt16, fCurrentIndexBuffer,
262cb93a386Sopenharmony_ci                                                       indexOffset, instanceCount,
263cb93a386Sopenharmony_ci                                                       baseVertex, baseInstance);
264cb93a386Sopenharmony_ci}
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_civoid CommandBuffer::onCopyTextureToBuffer(const skgpu::Texture* texture,
267cb93a386Sopenharmony_ci                                          SkIRect srcRect,
268cb93a386Sopenharmony_ci                                          const skgpu::Buffer* buffer,
269cb93a386Sopenharmony_ci                                          size_t bufferOffset,
270cb93a386Sopenharmony_ci                                          size_t bufferRowBytes) {
271cb93a386Sopenharmony_ci    SkASSERT(!fActiveRenderCommandEncoder);
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    id<MTLTexture> mtlTexture = static_cast<const Texture*>(texture)->mtlTexture();
274cb93a386Sopenharmony_ci    id<MTLBuffer> mtlBuffer = static_cast<const Buffer*>(buffer)->mtlBuffer();
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci    BlitCommandEncoder* blitCmdEncoder = this->getBlitCommandEncoder();
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO
279cb93a386Sopenharmony_ci    blitCmdEncoder->pushDebugGroup(@"readOrTransferPixels");
280cb93a386Sopenharmony_ci#endif
281cb93a386Sopenharmony_ci    blitCmdEncoder->copyFromTexture(mtlTexture, srcRect, mtlBuffer, bufferOffset, bufferRowBytes);
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci    if (fGpu->mtlCaps().isMac()) {
284cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC
285cb93a386Sopenharmony_ci        // Sync GPU data back to the CPU
286cb93a386Sopenharmony_ci        blitCmdEncoder->synchronizeResource(mtlBuffer);
287cb93a386Sopenharmony_ci#endif
288cb93a386Sopenharmony_ci    }
289cb93a386Sopenharmony_ci#ifdef SK_ENABLE_MTL_DEBUG_INFO
290cb93a386Sopenharmony_ci    blitCmdEncoder->popDebugGroup();
291cb93a386Sopenharmony_ci#endif
292cb93a386Sopenharmony_ci}
293cb93a386Sopenharmony_ci
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci} // namespace skgpu::mtl
296