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