• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 #include <memory>
16 
17 #include "include/core/SkTypes.h"
18 #include "include/ports/SkCFObject.h"
19 
20 #import <Metal/Metal.h>
21 
22 namespace skgpu::graphite {
23 class ComputePipeline;
24 class MtlBlitCommandEncoder;
25 class MtlComputeCommandEncoder;
26 class MtlRenderCommandEncoder;
27 class MtlResourceProvider;
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 
69     bool createNewMTLCommandBuffer();
70 
71     void onResetCommandBuffer() override;
72 
73     bool onAddRenderPass(const RenderPassDesc&,
74                          const Texture* colorTexture,
75                          const Texture* resolveTexture,
76                          const Texture* depthStencilTexture,
77                          SkRect viewport,
78                          const DrawPassList&) override;
79     bool onAddComputePass(DispatchGroupSpan) override;
80 
81     // Methods for populating a MTLRenderCommandEncoder:
82     bool beginRenderPass(const RenderPassDesc&,
83                          const Texture* colorTexture,
84                          const Texture* resolveTexture,
85                          const Texture* depthStencilTexture);
86     void endRenderPass();
87 
88     void addDrawPass(const DrawPass*);
89 
90     void bindGraphicsPipeline(const GraphicsPipeline*);
91     void setBlendConstants(float* blendConstants);
92 
93     void bindUniformBuffer(const BindBufferInfo& info, UniformSlot);
94     void bindDrawBuffers(const BindBufferInfo& vertices,
95                          const BindBufferInfo& instances,
96                          const BindBufferInfo& indices,
97                          const BindBufferInfo& indirect);
98     void bindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
99                            const Buffer* instanceBuffer, size_t instanceOffset);
100     void bindIndexBuffer(const Buffer* indexBuffer, size_t offset);
101     void bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset);
102 
103     void bindTextureAndSampler(const Texture*, const Sampler*, unsigned int bindIndex);
104 
105     void setScissor(unsigned int left, unsigned int top,
106                     unsigned int width, unsigned int height);
107     void setViewport(float x, float y, float width, float height,
108                      float minDepth, float maxDepth);
109 
110     void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount);
111     void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
112                      unsigned int baseVertex);
113     void drawInstanced(PrimitiveType type,
114                        unsigned int baseVertex, unsigned int vertexCount,
115                        unsigned int baseInstance, unsigned int instanceCount);
116     void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
117                               unsigned int indexCount, unsigned int baseVertex,
118                               unsigned int baseInstance, unsigned int instanceCount);
119     void drawIndirect(PrimitiveType type);
120     void drawIndexedIndirect(PrimitiveType type);
121 
122     // Methods for populating a MTLComputeCommandEncoder:
123     void beginComputePass();
124     void bindComputePipeline(const ComputePipeline*);
125     void bindBuffer(const Buffer* buffer, unsigned int offset, unsigned int index);
126     void bindTexture(const Texture* texture, unsigned int index);
127     void bindSampler(const Sampler* sampler, unsigned int index);
128     void dispatchThreadgroups(const WorkgroupSize& globalSize, const WorkgroupSize& localSize);
129     void dispatchThreadgroupsIndirect(const WorkgroupSize& localSize,
130                                       const Buffer* indirectBuffer,
131                                       size_t indirectBufferOffset);
132     void endComputePass();
133 
134     // Methods for populating a MTLBlitCommandEncoder:
135     bool onCopyBufferToBuffer(const Buffer* srcBuffer,
136                               size_t srcOffset,
137                               const Buffer* dstBuffer,
138                               size_t dstOffset,
139                               size_t size) override;
140     bool onCopyTextureToBuffer(const Texture*,
141                                SkIRect srcRect,
142                                const Buffer*,
143                                size_t bufferOffset,
144                                size_t bufferRowBytes) override;
145     bool onCopyBufferToTexture(const Buffer*,
146                                const Texture*,
147                                const BufferTextureCopyData* copyData,
148                                int count) override;
149     bool onCopyTextureToTexture(const Texture* src,
150                                 SkIRect srcRect,
151                                 const Texture* dst,
152                                 SkIPoint dstPoint,
153                                 int mipLevel) override;
154     bool onSynchronizeBufferToCpu(const Buffer*, bool* outDidResultInWork) override;
155     bool onClearBuffer(const Buffer*, size_t offset, size_t size) override;
156 
157     MtlBlitCommandEncoder* getBlitCommandEncoder();
158     void endBlitCommandEncoder();
159 
160     sk_cfp<id<MTLCommandBuffer>> fCommandBuffer;
161     sk_sp<MtlRenderCommandEncoder> fActiveRenderCommandEncoder;
162     sk_sp<MtlComputeCommandEncoder> fActiveComputeCommandEncoder;
163     sk_sp<MtlBlitCommandEncoder> fActiveBlitCommandEncoder;
164 
165     id<MTLBuffer> fCurrentIndexBuffer;
166     id<MTLBuffer> fCurrentIndirectBuffer;
167     size_t fCurrentIndexBufferOffset = 0;
168     size_t fCurrentIndirectBufferOffset = 0;
169 
170     // The command buffer will outlive the MtlQueueManager which owns the MTLCommandQueue.
171     id<MTLCommandQueue> fQueue;
172     const MtlSharedContext* fSharedContext;
173     MtlResourceProvider* fResourceProvider;
174 
175     // If true, the draw commands being added are entirely offscreen and can be skipped.
176     // This can happen if a recording is being replayed with a transform that moves the recorded
177     // commands outside of the render target bounds.
178     bool fDrawIsOffscreen = false;
179 };
180 
181 } // namespace skgpu::graphite
182 
183 #endif // skgpu_graphite_MtlCommandBuffer_DEFINED
184