xref: /aosp_15_r20/external/skia/src/gpu/graphite/mtl/MtlCommandBuffer.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef skgpu_graphite_MtlCommandBuffer_DEFINED
9 #define skgpu_graphite_MtlCommandBuffer_DEFINED
10 
11 #include "src/gpu/graphite/CommandBuffer.h"
12 #include "src/gpu/graphite/DrawPass.h"
13 #include "src/gpu/graphite/Log.h"
14 #include "src/gpu/graphite/mtl/MtlResourceProvider.h"
15 
16 #include <memory>
17 
18 #include "include/core/SkTypes.h"
19 #include "include/ports/SkCFObject.h"
20 
21 #import <Metal/Metal.h>
22 
23 namespace skgpu::graphite {
24 class ComputePipeline;
25 class MtlBlitCommandEncoder;
26 class MtlComputeCommandEncoder;
27 class MtlRenderCommandEncoder;
28 class MtlSharedContext;
29 struct WorkgroupSize;
30 
31 class MtlCommandBuffer final : public CommandBuffer {
32 public:
33     static std::unique_ptr<MtlCommandBuffer> Make(id<MTLCommandQueue>,
34                                                   const MtlSharedContext*,
35                                                   MtlResourceProvider*);
36     ~MtlCommandBuffer() override;
37 
38     bool setNewCommandBufferResources() override;
39 
40     void addWaitSemaphores(size_t numWaitSemaphores,
41                            const BackendSemaphore* waitSemaphores) override;
42     void addSignalSemaphores(size_t numSignalSemaphores,
43                              const BackendSemaphore* signalSemaphores) override;
44 
isFinished()45     bool isFinished() {
46         return (*fCommandBuffer).status == MTLCommandBufferStatusCompleted ||
47                (*fCommandBuffer).status == MTLCommandBufferStatusError;
48 
49     }
waitUntilFinished()50     void waitUntilFinished() {
51         // TODO: it's not clear what do to if status is Enqueued. Commit and then wait?
52         if ((*fCommandBuffer).status == MTLCommandBufferStatusScheduled ||
53             (*fCommandBuffer).status == MTLCommandBufferStatusCommitted) {
54             [(*fCommandBuffer) waitUntilCompleted];
55         }
56         if (!this->isFinished()) {
57             SKGPU_LOG_E("Unfinished command buffer status: %d",
58                         (int)(*fCommandBuffer).status);
59             SkASSERT(false);
60         }
61     }
62     bool commit();
63 
64 private:
65     MtlCommandBuffer(id<MTLCommandQueue>,
66                      const MtlSharedContext* sharedContext,
67                      MtlResourceProvider* resourceProvider);
68 
resourceProvider()69     ResourceProvider* resourceProvider() const override { return fResourceProvider; }
70 
71     bool createNewMTLCommandBuffer();
72 
73     void onResetCommandBuffer() override;
74 
75     bool onAddRenderPass(const RenderPassDesc&,
76                          SkIRect renderPassBounds,
77                          const Texture* colorTexture,
78                          const Texture* resolveTexture,
79                          const Texture* depthStencilTexture,
80                          SkIRect viewport,
81                          const DrawPassList&) override;
82     bool onAddComputePass(DispatchGroupSpan) override;
83 
84     // Methods for populating a MTLRenderCommandEncoder:
85     bool beginRenderPass(const RenderPassDesc&,
86                          const Texture* colorTexture,
87                          const Texture* resolveTexture,
88                          const Texture* depthStencilTexture);
89     void endRenderPass();
90 
91     void addDrawPass(const DrawPass*);
92 
93     void updateIntrinsicUniforms(SkIRect viewport);
94 
95     void bindGraphicsPipeline(const GraphicsPipeline*);
96     void setBlendConstants(float* blendConstants);
97 
98     void bindUniformBuffer(const BindBufferInfo& info, UniformSlot);
99     void bindDrawBuffers(const BindBufferInfo& vertices,
100                          const BindBufferInfo& instances,
101                          const BindBufferInfo& indices,
102                          const BindBufferInfo& indirect);
103     void bindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
104                            const Buffer* instanceBuffer, size_t instanceOffset);
105     void bindIndexBuffer(const Buffer* indexBuffer, size_t offset);
106     void bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset);
107 
108     void bindTextureAndSampler(const Texture*, const Sampler*, unsigned int bindIndex);
109 
110     void setScissor(const Scissor&);
111     void setViewport(float x, float y, float width, float height,
112                      float minDepth, float maxDepth);
113 
114     void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount);
115     void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
116                      unsigned int baseVertex);
117     void drawInstanced(PrimitiveType type,
118                        unsigned int baseVertex, unsigned int vertexCount,
119                        unsigned int baseInstance, unsigned int instanceCount);
120     void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
121                               unsigned int indexCount, unsigned int baseVertex,
122                               unsigned int baseInstance, unsigned int instanceCount);
123     void drawIndirect(PrimitiveType type);
124     void drawIndexedIndirect(PrimitiveType type);
125 
126     // Methods for populating a MTLComputeCommandEncoder:
127     void beginComputePass();
128     void bindComputePipeline(const ComputePipeline*);
129     void bindBuffer(const Buffer* buffer, unsigned int offset, unsigned int index);
130     void bindTexture(const Texture* texture, unsigned int index);
131     void bindSampler(const Sampler* sampler, unsigned int index);
132     void dispatchThreadgroups(const WorkgroupSize& globalSize, const WorkgroupSize& localSize);
133     void dispatchThreadgroupsIndirect(const WorkgroupSize& localSize,
134                                       const Buffer* indirectBuffer,
135                                       size_t indirectBufferOffset);
136     void endComputePass();
137 
138     // Methods for populating a MTLBlitCommandEncoder:
139     bool onCopyBufferToBuffer(const Buffer* srcBuffer,
140                               size_t srcOffset,
141                               const Buffer* dstBuffer,
142                               size_t dstOffset,
143                               size_t size) override;
144     bool onCopyTextureToBuffer(const Texture*,
145                                SkIRect srcRect,
146                                const Buffer*,
147                                size_t bufferOffset,
148                                size_t bufferRowBytes) override;
149     bool onCopyBufferToTexture(const Buffer*,
150                                const Texture*,
151                                const BufferTextureCopyData* copyData,
152                                int count) override;
153     bool onCopyTextureToTexture(const Texture* src,
154                                 SkIRect srcRect,
155                                 const Texture* dst,
156                                 SkIPoint dstPoint,
157                                 int mipLevel) override;
158     bool onSynchronizeBufferToCpu(const Buffer*, bool* outDidResultInWork) override;
159     bool onClearBuffer(const Buffer*, size_t offset, size_t size) override;
160 
161     MtlBlitCommandEncoder* getBlitCommandEncoder();
162     void endBlitCommandEncoder();
163 
164     sk_cfp<id<MTLCommandBuffer>> fCommandBuffer;
165     sk_sp<MtlRenderCommandEncoder> fActiveRenderCommandEncoder;
166     sk_sp<MtlComputeCommandEncoder> fActiveComputeCommandEncoder;
167     sk_sp<MtlBlitCommandEncoder> fActiveBlitCommandEncoder;
168 
169     id<MTLBuffer> fCurrentIndexBuffer;
170     id<MTLBuffer> fCurrentIndirectBuffer;
171     size_t fCurrentIndexBufferOffset = 0;
172     size_t fCurrentIndirectBufferOffset = 0;
173 
174     // The command buffer will outlive the MtlQueueManager which owns the MTLCommandQueue.
175     id<MTLCommandQueue> fQueue;
176     const MtlSharedContext* fSharedContext;
177     MtlResourceProvider* fResourceProvider;
178 
179     // If true, the draw commands being added are entirely offscreen and can be skipped.
180     // This can happen if a recording is being replayed with a transform that moves the recorded
181     // commands outside of the render target bounds.
182     bool fDrawIsOffscreen = false;
183 };
184 
185 } // namespace skgpu::graphite
186 
187 #endif // skgpu_graphite_MtlCommandBuffer_DEFINED
188