• 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 #ifdef SK_ENABLE_PIET_GPU
21 #include "src/gpu/piet/Render.h"
22 #endif
23 
24 #import <Metal/Metal.h>
25 
26 namespace skgpu::graphite {
27 class MtlBlitCommandEncoder;
28 class MtlComputeCommandEncoder;
29 class MtlRenderCommandEncoder;
30 class MtlResourceProvider;
31 class MtlSharedContext;
32 
33 class MtlCommandBuffer final : public CommandBuffer {
34 public:
35     static std::unique_ptr<MtlCommandBuffer> Make(id<MTLCommandQueue>,
36                                                   const MtlSharedContext*,
37                                                   MtlResourceProvider*);
38     ~MtlCommandBuffer() override;
39 
40     bool setNewCommandBufferResources() override;
41 
isFinished()42     bool isFinished() {
43         return (*fCommandBuffer).status == MTLCommandBufferStatusCompleted ||
44                (*fCommandBuffer).status == MTLCommandBufferStatusError;
45 
46     }
waitUntilFinished()47     void waitUntilFinished() {
48         // TODO: it's not clear what do to if status is Enqueued. Commit and then wait?
49         if ((*fCommandBuffer).status == MTLCommandBufferStatusScheduled ||
50             (*fCommandBuffer).status == MTLCommandBufferStatusCommitted) {
51             [(*fCommandBuffer) waitUntilCompleted];
52         }
53         if (!this->isFinished()) {
54             SKGPU_LOG_E("Unfinished command buffer status: %d",
55                         (int)(*fCommandBuffer).status);
56             SkASSERT(false);
57         }
58     }
59     bool commit();
60 
61 #ifdef SK_ENABLE_PIET_GPU
setPietRenderer(const skgpu::piet::MtlRenderer * renderer)62     void setPietRenderer(const skgpu::piet::MtlRenderer* renderer) { fPietRenderer = renderer; }
63 #endif
64 
65 private:
66     MtlCommandBuffer(id<MTLCommandQueue>,
67                      const MtlSharedContext* sharedContext,
68                      MtlResourceProvider* resourceProvider);
69 
70     bool createNewMTLCommandBuffer();
71 
72     void onResetCommandBuffer() override;
73 
74     bool onAddRenderPass(const RenderPassDesc&,
75                          const Texture* colorTexture,
76                          const Texture* resolveTexture,
77                          const Texture* depthStencilTexture,
78                          SkRect viewport,
79                          const std::vector<std::unique_ptr<DrawPass>>& drawPasses) override;
80     bool onAddComputePass(const ComputePassDesc&,
81                           const ComputePipeline*,
82                           const std::vector<ResourceBinding>& bindings) 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 bindGraphicsPipeline(const GraphicsPipeline*);
94     void setBlendConstants(float* blendConstants);
95 
96     void bindUniformBuffer(const BindBufferInfo& info, UniformSlot);
97     void bindDrawBuffers(const BindBufferInfo& vertices,
98                          const BindBufferInfo& instances,
99                          const BindBufferInfo& indices,
100                          const BindBufferInfo& indirect);
101     void bindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
102                            const Buffer* instanceBuffer, size_t instanceOffset);
103     void bindIndexBuffer(const Buffer* indexBuffer, size_t offset);
104     void bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset);
105 
106     void bindTextureAndSampler(const Texture*, const Sampler*, unsigned int bindIndex);
107 
108     void setScissor(unsigned int left, unsigned int top,
109                     unsigned int width, unsigned int height);
110     void setViewport(float x, float y, float width, float height,
111                      float minDepth, float maxDepth);
112 
113     void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount);
114     void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
115                      unsigned int baseVertex);
116     void drawInstanced(PrimitiveType type,
117                        unsigned int baseVertex, unsigned int vertexCount,
118                        unsigned int baseInstance, unsigned int instanceCount);
119     void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
120                               unsigned int indexCount, unsigned int baseVertex,
121                               unsigned int baseInstance, unsigned int instanceCount);
122     void drawIndirect(PrimitiveType type);
123     void drawIndexedIndirect(PrimitiveType type);
124 
125     // Methods for populating a MTLComputeCommandEncoder:
126     void beginComputePass();
127     void bindComputePipeline(const ComputePipeline*);
128     void bindBuffer(const Buffer* buffer, unsigned int offset, unsigned int index);
129     void dispatchThreadgroups(const WorkgroupSize& globalSize, const WorkgroupSize& localSize);
130     void endComputePass();
131 
132     // Methods for populating a MTLBlitCommandEncoder:
133     bool onCopyBufferToBuffer(const Buffer* srcBuffer,
134                               size_t srcOffset,
135                               const Buffer* dstBuffer,
136                               size_t dstOffset,
137                               size_t size) override;
138     bool onCopyTextureToBuffer(const Texture*,
139                                SkIRect srcRect,
140                                const Buffer*,
141                                size_t bufferOffset,
142                                size_t bufferRowBytes) override;
143     bool onCopyBufferToTexture(const Buffer*,
144                                const Texture*,
145                                const BufferTextureCopyData* copyData,
146                                int count) override;
147     bool onCopyTextureToTexture(const Texture* src,
148                                 SkIRect srcRect,
149                                 const Texture* dst,
150                                 SkIPoint dstPoint) override;
151     bool onSynchronizeBufferToCpu(const Buffer*, bool* outDidResultInWork) override;
152     bool onClearBuffer(const Buffer*, size_t offset, size_t size) override;
153 
154 #ifdef SK_ENABLE_PIET_GPU
155     void onRenderPietScene(const skgpu::piet::Scene& scene, const Texture* target) override;
156 #endif
157 
158     MtlBlitCommandEncoder* getBlitCommandEncoder();
159     void endBlitCommandEncoder();
160 
161     sk_cfp<id<MTLCommandBuffer>> fCommandBuffer;
162     sk_sp<MtlRenderCommandEncoder> fActiveRenderCommandEncoder;
163     sk_sp<MtlComputeCommandEncoder> fActiveComputeCommandEncoder;
164     sk_sp<MtlBlitCommandEncoder> fActiveBlitCommandEncoder;
165 
166     id<MTLBuffer> fCurrentIndexBuffer;
167     id<MTLBuffer> fCurrentIndirectBuffer;
168     size_t fCurrentIndexBufferOffset = 0;
169     size_t fCurrentIndirectBufferOffset = 0;
170 
171     // The command buffer will outlive the MtlQueueManager which owns the MTLCommandQueue.
172     id<MTLCommandQueue> fQueue;
173     const MtlSharedContext* fSharedContext;
174     MtlResourceProvider* fResourceProvider;
175 
176     // If true, the draw commands being added are entirely offscreen and can be skipped.
177     // This can happen if a recording is being replayed with a transform that moves the recorded
178     // commands outside of the render target bounds.
179     bool fDrawIsOffscreen = false;
180 
181 #ifdef SK_ENABLE_PIET_GPU
182     const skgpu::piet::MtlRenderer* fPietRenderer = nullptr;  // owned by MtlQueueManager
183 #endif
184 };
185 
186 } // namespace skgpu::graphite
187 
188 #endif // skgpu_graphite_MtlCommandBuffer_DEFINED
189