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