• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // mtl_command_buffer.h:
7 //    Defines the wrapper classes for Metal's MTLCommandEncoder, MTLCommandQueue and
8 //    MTLCommandBuffer.
9 //
10 
11 #ifndef LIBANGLE_RENDERER_METAL_COMMANDENBUFFERMTL_H_
12 #define LIBANGLE_RENDERER_METAL_COMMANDENBUFFERMTL_H_
13 
14 #import <Metal/Metal.h>
15 #import <QuartzCore/CAMetalLayer.h>
16 
17 #include <deque>
18 #include <memory>
19 #include <mutex>
20 #include <thread>
21 #include <unordered_set>
22 #include <vector>
23 
24 #include "common/FixedVector.h"
25 #include "common/angleutils.h"
26 #include "libANGLE/renderer/metal/mtl_common.h"
27 #include "libANGLE/renderer/metal/mtl_resources.h"
28 #include "libANGLE/renderer/metal/mtl_state_cache.h"
29 
30 namespace rx
31 {
32 namespace mtl
33 {
34 
35 enum CommandBufferFinishOperation
36 {
37     NoWait,
38     WaitUntilScheduled,
39     WaitUntilFinished
40 };
41 
42 class CommandBuffer;
43 class CommandEncoder;
44 class RenderCommandEncoder;
45 class OcclusionQueryPool;
46 
47 class CommandQueue final : public WrappedObject<id<MTLCommandQueue>>, angle::NonCopyable
48 {
49   public:
50     void reset();
51     void set(id<MTLCommandQueue> metalQueue);
52 
53     void finishAllCommands();
54 
55     // This method will ensure that every GPU command buffer using this resource will finish before
56     // returning. Note: this doesn't include the "in-progress" command buffer, i.e. the one hasn't
57     // been commmitted yet. It's the responsibility of caller to make sure that command buffer is
58     // commited/flushed first before calling this method.
59     void ensureResourceReadyForCPU(const ResourceRef &resource);
60     void ensureResourceReadyForCPU(Resource *resource);
61 
62     // Check whether the resource is being used by any command buffer still running on GPU.
63     // This must be called before attempting to read the content of resource on CPU side.
isResourceBeingUsedByGPU(const ResourceRef & resource)64     bool isResourceBeingUsedByGPU(const ResourceRef &resource) const
65     {
66         return isResourceBeingUsedByGPU(resource.get());
67     }
68     bool isResourceBeingUsedByGPU(const Resource *resource) const;
69 
70     // Checks whether the last command buffer that uses the given resource has been committed or not
71     bool resourceHasPendingWorks(const Resource *resource) const;
72 
73     CommandQueue &operator=(id<MTLCommandQueue> metalQueue)
74     {
75         set(metalQueue);
76         return *this;
77     }
78 
79     AutoObjCPtr<id<MTLCommandBuffer>> makeMetalCommandBuffer(uint64_t *queueSerialOut);
80     void onCommandBufferCommitted(id<MTLCommandBuffer> buf, uint64_t serial);
81 
82   private:
83     void onCommandBufferCompleted(id<MTLCommandBuffer> buf, uint64_t serial);
84     using ParentClass = WrappedObject<id<MTLCommandQueue>>;
85 
86     struct CmdBufferQueueEntry
87     {
88         AutoObjCPtr<id<MTLCommandBuffer>> buffer;
89         uint64_t serial;
90     };
91     std::deque<CmdBufferQueueEntry> mMetalCmdBuffers;
92     std::deque<CmdBufferQueueEntry> mMetalCmdBuffersTmp;
93 
94     uint64_t mQueueSerialCounter = 1;
95     std::atomic<uint64_t> mCommittedBufferSerial{0};
96     std::atomic<uint64_t> mCompletedBufferSerial{0};
97 
98     mutable std::mutex mLock;
99 };
100 
101 class CommandBuffer final : public WrappedObject<id<MTLCommandBuffer>>, angle::NonCopyable
102 {
103   public:
104     CommandBuffer(CommandQueue *cmdQueue);
105     ~CommandBuffer();
106 
107     // This method must be called so that command encoder can be used.
108     void restart();
109 
110     // Return true if command buffer can be encoded into. Return false if it has been committed
111     // and hasn't been restarted.
112     bool ready() const;
113     void commit(CommandBufferFinishOperation operation);
114 
115     void present(id<CAMetalDrawable> presentationDrawable);
116 
117     void setWriteDependency(const ResourceRef &resource);
118     void setReadDependency(const ResourceRef &resource);
119     void setReadDependency(Resource *resourcePtr);
120 
121     void queueEventSignal(const mtl::SharedEventRef &event, uint64_t value);
122     void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value);
123 
124     void insertDebugSign(const std::string &marker);
125     void pushDebugGroup(const std::string &marker);
126     void popDebugGroup();
127 
cmdQueue()128     CommandQueue &cmdQueue() { return mCmdQueue; }
129 
130     // Private use only
131     void setActiveCommandEncoder(CommandEncoder *encoder);
132     void invalidateActiveCommandEncoder(CommandEncoder *encoder);
133 
134   private:
135     void set(id<MTLCommandBuffer> metalBuffer);
136     void cleanup();
137 
138     bool readyImpl() const;
139     bool commitImpl();
140     void forceEndingCurrentEncoder();
141 
142     void setPendingEvents();
143     void setEventImpl(const mtl::SharedEventRef &event, uint64_t value);
144     void waitEventImpl(const mtl::SharedEventRef &event, uint64_t value);
145 
146     void pushDebugGroupImpl(const std::string &marker);
147     void popDebugGroupImpl();
148 
149     using ParentClass = WrappedObject<id<MTLCommandBuffer>>;
150 
151     CommandQueue &mCmdQueue;
152 
153     CommandEncoder *mActiveCommandEncoder = nullptr;
154 
155     uint64_t mQueueSerial = 0;
156 
157     mutable std::mutex mLock;
158 
159     std::vector<std::string> mPendingDebugSigns;
160     std::vector<std::pair<mtl::SharedEventRef, uint64_t>> mPendingSignalEvents;
161 
162     std::vector<std::string> mDebugGroups;
163 
164     bool mCommitted = false;
165 };
166 
167 class CommandEncoder : public WrappedObject<id<MTLCommandEncoder>>, angle::NonCopyable
168 {
169   public:
170     enum Type
171     {
172         RENDER,
173         BLIT,
174         COMPUTE,
175     };
176 
177     virtual ~CommandEncoder();
178 
179     virtual void endEncoding();
180 
181     virtual void reset();
getType()182     Type getType() const { return mType; }
183 
184     CommandEncoder &markResourceBeingWrittenByGPU(const BufferRef &buffer);
185     CommandEncoder &markResourceBeingWrittenByGPU(const TextureRef &texture);
186 
187     void insertDebugSign(NSString *label);
188 
189     virtual void pushDebugGroup(NSString *label);
190     virtual void popDebugGroup();
191 
192   protected:
193     using ParentClass = WrappedObject<id<MTLCommandEncoder>>;
194 
195     CommandEncoder(CommandBuffer *cmdBuffer, Type type);
196 
cmdBuffer()197     CommandBuffer &cmdBuffer() { return mCmdBuffer; }
cmdQueue()198     CommandQueue &cmdQueue() { return mCmdBuffer.cmdQueue(); }
199 
200     void set(id<MTLCommandEncoder> metalCmdEncoder);
201 
202     virtual void insertDebugSignImpl(NSString *marker);
203 
204   private:
205     const Type mType;
206     CommandBuffer &mCmdBuffer;
207 };
208 
209 // Stream to store commands before encoding them into the real MTLCommandEncoder
210 class IntermediateCommandStream
211 {
212   public:
213     template <typename T>
push(const T & val)214     inline IntermediateCommandStream &push(const T &val)
215     {
216         auto ptr = reinterpret_cast<const uint8_t *>(&val);
217         mBuffer.insert(mBuffer.end(), ptr, ptr + sizeof(T));
218         return *this;
219     }
220 
push(const uint8_t * bytes,size_t len)221     inline IntermediateCommandStream &push(const uint8_t *bytes, size_t len)
222     {
223         mBuffer.insert(mBuffer.end(), bytes, bytes + len);
224         return *this;
225     }
226 
227     template <typename T>
peek()228     inline T peek()
229     {
230         ASSERT(mReadPtr <= mBuffer.size() - sizeof(T));
231         T re;
232         auto ptr = reinterpret_cast<uint8_t *>(&re);
233         std::copy(mBuffer.data() + mReadPtr, mBuffer.data() + mReadPtr + sizeof(T), ptr);
234         return re;
235     }
236 
237     template <typename T>
fetch()238     inline T fetch()
239     {
240         auto re = peek<T>();
241         mReadPtr += sizeof(T);
242         return re;
243     }
244 
fetch(size_t bytes)245     inline const uint8_t *fetch(size_t bytes)
246     {
247         ASSERT(mReadPtr <= mBuffer.size() - bytes);
248         auto cur = mReadPtr;
249         mReadPtr += bytes;
250         return mBuffer.data() + cur;
251     }
252 
clear()253     inline void clear()
254     {
255         mBuffer.clear();
256         mReadPtr = 0;
257     }
258 
resetReadPtr(size_t readPtr)259     inline void resetReadPtr(size_t readPtr)
260     {
261         ASSERT(readPtr <= mBuffer.size());
262         mReadPtr = readPtr;
263     }
264 
good()265     inline bool good() const { return mReadPtr < mBuffer.size(); }
266 
267   private:
268     std::vector<uint8_t> mBuffer;
269     size_t mReadPtr = 0;
270 };
271 
272 // Per shader stage's states
273 struct RenderCommandEncoderShaderStates
274 {
275     RenderCommandEncoderShaderStates();
276 
277     void reset();
278 
279     std::array<id<MTLBuffer>, kMaxShaderBuffers> buffers;
280     std::array<uint32_t, kMaxShaderBuffers> bufferOffsets;
281     std::array<id<MTLSamplerState>, kMaxShaderSamplers> samplers;
282     std::array<Optional<std::pair<float, float>>, kMaxShaderSamplers> samplerLodClamps;
283     std::array<id<MTLTexture>, kMaxShaderSamplers> textures;
284 };
285 
286 // Per render pass's states
287 struct RenderCommandEncoderStates
288 {
289     RenderCommandEncoderStates();
290 
291     void reset();
292 
293     id<MTLRenderPipelineState> renderPipeline;
294 
295     MTLTriangleFillMode triangleFillMode;
296     MTLWinding winding;
297     MTLCullMode cullMode;
298 
299     id<MTLDepthStencilState> depthStencilState;
300     float depthBias, depthSlopeScale, depthClamp;
301 
302     uint32_t stencilFrontRef, stencilBackRef;
303 
304     Optional<MTLViewport> viewport;
305     Optional<MTLScissorRect> scissorRect;
306 
307     std::array<float, 4> blendColor;
308 
309     gl::ShaderMap<RenderCommandEncoderShaderStates> perShaderStates;
310 
311     MTLVisibilityResultMode visibilityResultMode;
312     size_t visibilityResultBufferOffset;
313 };
314 
315 // Encoder for encoding render commands
316 class RenderCommandEncoder final : public CommandEncoder
317 {
318   public:
319     RenderCommandEncoder(CommandBuffer *cmdBuffer, const OcclusionQueryPool &queryPool);
320     ~RenderCommandEncoder() override;
321 
322     // override CommandEncoder
valid()323     bool valid() const { return mRecording; }
324     void reset() override;
325     void endEncoding() override;
326 
327     // Restart the encoder so that new commands can be encoded.
328     // NOTE: parent CommandBuffer's restart() must be called before this.
329     RenderCommandEncoder &restart(const RenderPassDesc &desc);
330 
331     RenderCommandEncoder &setRenderPipelineState(id<MTLRenderPipelineState> state);
332     RenderCommandEncoder &setTriangleFillMode(MTLTriangleFillMode mode);
333     RenderCommandEncoder &setFrontFacingWinding(MTLWinding winding);
334     RenderCommandEncoder &setCullMode(MTLCullMode mode);
335 
336     RenderCommandEncoder &setDepthStencilState(id<MTLDepthStencilState> state);
337     RenderCommandEncoder &setDepthBias(float depthBias, float slopeScale, float clamp);
338     RenderCommandEncoder &setStencilRefVals(uint32_t frontRef, uint32_t backRef);
339     RenderCommandEncoder &setStencilRefVal(uint32_t ref);
340 
341     RenderCommandEncoder &setViewport(const MTLViewport &viewport);
342     RenderCommandEncoder &setScissorRect(const MTLScissorRect &rect);
343 
344     RenderCommandEncoder &setBlendColor(float r, float g, float b, float a);
345 
setVertexBuffer(const BufferRef & buffer,uint32_t offset,uint32_t index)346     RenderCommandEncoder &setVertexBuffer(const BufferRef &buffer, uint32_t offset, uint32_t index)
347     {
348         return setBuffer(gl::ShaderType::Vertex, buffer, offset, index);
349     }
setVertexBytes(const uint8_t * bytes,size_t size,uint32_t index)350     RenderCommandEncoder &setVertexBytes(const uint8_t *bytes, size_t size, uint32_t index)
351     {
352         return setBytes(gl::ShaderType::Vertex, bytes, size, index);
353     }
354     template <typename T>
setVertexData(const T & data,uint32_t index)355     RenderCommandEncoder &setVertexData(const T &data, uint32_t index)
356     {
357         return setVertexBytes(reinterpret_cast<const uint8_t *>(&data), sizeof(T), index);
358     }
setVertexSamplerState(id<MTLSamplerState> state,float lodMinClamp,float lodMaxClamp,uint32_t index)359     RenderCommandEncoder &setVertexSamplerState(id<MTLSamplerState> state,
360                                                 float lodMinClamp,
361                                                 float lodMaxClamp,
362                                                 uint32_t index)
363     {
364         return setSamplerState(gl::ShaderType::Vertex, state, lodMinClamp, lodMaxClamp, index);
365     }
setVertexTexture(const TextureRef & texture,uint32_t index)366     RenderCommandEncoder &setVertexTexture(const TextureRef &texture, uint32_t index)
367     {
368         return setTexture(gl::ShaderType::Vertex, texture, index);
369     }
370 
setFragmentBuffer(const BufferRef & buffer,uint32_t offset,uint32_t index)371     RenderCommandEncoder &setFragmentBuffer(const BufferRef &buffer,
372                                             uint32_t offset,
373                                             uint32_t index)
374     {
375         return setBuffer(gl::ShaderType::Fragment, buffer, offset, index);
376     }
setFragmentBytes(const uint8_t * bytes,size_t size,uint32_t index)377     RenderCommandEncoder &setFragmentBytes(const uint8_t *bytes, size_t size, uint32_t index)
378     {
379         return setBytes(gl::ShaderType::Fragment, bytes, size, index);
380     }
381     template <typename T>
setFragmentData(const T & data,uint32_t index)382     RenderCommandEncoder &setFragmentData(const T &data, uint32_t index)
383     {
384         return setFragmentBytes(reinterpret_cast<const uint8_t *>(&data), sizeof(T), index);
385     }
setFragmentSamplerState(id<MTLSamplerState> state,float lodMinClamp,float lodMaxClamp,uint32_t index)386     RenderCommandEncoder &setFragmentSamplerState(id<MTLSamplerState> state,
387                                                   float lodMinClamp,
388                                                   float lodMaxClamp,
389                                                   uint32_t index)
390     {
391         return setSamplerState(gl::ShaderType::Fragment, state, lodMinClamp, lodMaxClamp, index);
392     }
setFragmentTexture(const TextureRef & texture,uint32_t index)393     RenderCommandEncoder &setFragmentTexture(const TextureRef &texture, uint32_t index)
394     {
395         return setTexture(gl::ShaderType::Fragment, texture, index);
396     }
397 
398     RenderCommandEncoder &setBuffer(gl::ShaderType shaderType,
399                                     const BufferRef &buffer,
400                                     uint32_t offset,
401                                     uint32_t index);
402     RenderCommandEncoder &setBufferForWrite(gl::ShaderType shaderType,
403                                             const BufferRef &buffer,
404                                             uint32_t offset,
405                                             uint32_t index);
406     RenderCommandEncoder &setBytes(gl::ShaderType shaderType,
407                                    const uint8_t *bytes,
408                                    size_t size,
409                                    uint32_t index);
410     template <typename T>
setData(gl::ShaderType shaderType,const T & data,uint32_t index)411     RenderCommandEncoder &setData(gl::ShaderType shaderType, const T &data, uint32_t index)
412     {
413         return setBytes(shaderType, reinterpret_cast<const uint8_t *>(&data), sizeof(T), index);
414     }
415     RenderCommandEncoder &setSamplerState(gl::ShaderType shaderType,
416                                           id<MTLSamplerState> state,
417                                           float lodMinClamp,
418                                           float lodMaxClamp,
419                                           uint32_t index);
420     RenderCommandEncoder &setTexture(gl::ShaderType shaderType,
421                                      const TextureRef &texture,
422                                      uint32_t index);
423 
424     RenderCommandEncoder &draw(MTLPrimitiveType primitiveType,
425                                uint32_t vertexStart,
426                                uint32_t vertexCount);
427     RenderCommandEncoder &drawInstanced(MTLPrimitiveType primitiveType,
428                                         uint32_t vertexStart,
429                                         uint32_t vertexCount,
430                                         uint32_t instances);
431     RenderCommandEncoder &drawIndexed(MTLPrimitiveType primitiveType,
432                                       uint32_t indexCount,
433                                       MTLIndexType indexType,
434                                       const BufferRef &indexBuffer,
435                                       size_t bufferOffset);
436     RenderCommandEncoder &drawIndexedInstanced(MTLPrimitiveType primitiveType,
437                                                uint32_t indexCount,
438                                                MTLIndexType indexType,
439                                                const BufferRef &indexBuffer,
440                                                size_t bufferOffset,
441                                                uint32_t instances);
442     RenderCommandEncoder &drawIndexedInstancedBaseVertex(MTLPrimitiveType primitiveType,
443                                                          uint32_t indexCount,
444                                                          MTLIndexType indexType,
445                                                          const BufferRef &indexBuffer,
446                                                          size_t bufferOffset,
447                                                          uint32_t instances,
448                                                          uint32_t baseVertex);
449 
450     RenderCommandEncoder &setVisibilityResultMode(MTLVisibilityResultMode mode, size_t offset);
451 
452     RenderCommandEncoder &useResource(const BufferRef &resource,
453                                       MTLResourceUsage usage,
454                                       mtl::RenderStages states);
455 
456     RenderCommandEncoder &memoryBarrierWithResource(const BufferRef &resource,
457                                                     mtl::RenderStages after,
458                                                     mtl::RenderStages before);
459 
460     RenderCommandEncoder &setColorStoreAction(MTLStoreAction action, uint32_t colorAttachmentIndex);
461     // Set store action for every color attachment.
462     RenderCommandEncoder &setColorStoreAction(MTLStoreAction action);
463 
464     RenderCommandEncoder &setDepthStencilStoreAction(MTLStoreAction depthStoreAction,
465                                                      MTLStoreAction stencilStoreAction);
466     RenderCommandEncoder &setDepthStoreAction(MTLStoreAction action);
467     RenderCommandEncoder &setStencilStoreAction(MTLStoreAction action);
468 
469     // Set storeaction for every color & depth & stencil attachment.
470     RenderCommandEncoder &setStoreAction(MTLStoreAction action);
471 
472     // Change the render pass's loadAction. Note that this operation is only allowed when there
473     // is no draw call recorded yet.
474     RenderCommandEncoder &setColorLoadAction(MTLLoadAction action,
475                                              const MTLClearColor &clearValue,
476                                              uint32_t colorAttachmentIndex);
477     RenderCommandEncoder &setDepthLoadAction(MTLLoadAction action, double clearValue);
478     RenderCommandEncoder &setStencilLoadAction(MTLLoadAction action, uint32_t clearValue);
479 
480     void setLabel(NSString *label);
481 
482     void pushDebugGroup(NSString *label) override;
483     void popDebugGroup() override;
484 
renderPassDesc()485     const RenderPassDesc &renderPassDesc() const { return mRenderPassDesc; }
hasDrawCalls()486     bool hasDrawCalls() const { return mHasDrawCalls; }
487 
488   private:
489     // Override CommandEncoder
get()490     id<MTLRenderCommandEncoder> get()
491     {
492         return static_cast<id<MTLRenderCommandEncoder>>(CommandEncoder::get());
493     }
494     void insertDebugSignImpl(NSString *label) override;
495 
496     void initAttachmentWriteDependencyAndScissorRect(const RenderPassAttachmentDesc &attachment);
497     void initWriteDependency(const TextureRef &texture);
498 
499     void finalizeLoadStoreAction(MTLRenderPassAttachmentDescriptor *objCRenderPassAttachment);
500 
501     void encodeMetalEncoder();
502     void simulateDiscardFramebuffer();
503     void endEncodingImpl(bool considerDiscardSimulation);
504 
505     RenderCommandEncoder &commonSetBuffer(gl::ShaderType shaderType,
506                                           id<MTLBuffer> mtlBuffer,
507                                           uint32_t offset,
508                                           uint32_t index);
509 
510     RenderPassDesc mRenderPassDesc;
511     // Cached Objective-C render pass desc to avoid re-allocate every frame.
512     mtl::AutoObjCObj<MTLRenderPassDescriptor> mCachedRenderPassDescObjC;
513 
514     mtl::AutoObjCObj<NSString> mLabel;
515 
516     MTLScissorRect mRenderPassMaxScissorRect;
517 
518     const OcclusionQueryPool &mOcclusionQueryPool;
519     bool mRecording    = false;
520     bool mHasDrawCalls = false;
521     IntermediateCommandStream mCommands;
522 
523     gl::ShaderMap<uint8_t> mSetBufferCmds;
524     gl::ShaderMap<uint8_t> mSetBufferOffsetCmds;
525     gl::ShaderMap<uint8_t> mSetBytesCmds;
526     gl::ShaderMap<uint8_t> mSetTextureCmds;
527     gl::ShaderMap<uint8_t> mSetSamplerCmds;
528 
529     RenderCommandEncoderStates mStateCache = {};
530 
531     bool mPipelineStateSet = false;
532 };
533 
534 class BlitCommandEncoder final : public CommandEncoder
535 {
536   public:
537     BlitCommandEncoder(CommandBuffer *cmdBuffer);
538     ~BlitCommandEncoder() override;
539 
540     // Restart the encoder so that new commands can be encoded.
541     // NOTE: parent CommandBuffer's restart() must be called before this.
542     BlitCommandEncoder &restart();
543 
544     BlitCommandEncoder &copyBuffer(const BufferRef &src,
545                                    size_t srcOffset,
546                                    const BufferRef &dst,
547                                    size_t dstOffset,
548                                    size_t size);
549 
550     BlitCommandEncoder &copyBufferToTexture(const BufferRef &src,
551                                             size_t srcOffset,
552                                             size_t srcBytesPerRow,
553                                             size_t srcBytesPerImage,
554                                             MTLSize srcSize,
555                                             const TextureRef &dst,
556                                             uint32_t dstSlice,
557                                             MipmapNativeLevel dstLevel,
558                                             MTLOrigin dstOrigin,
559                                             MTLBlitOption blitOption);
560 
561     BlitCommandEncoder &copyTextureToBuffer(const TextureRef &src,
562                                             uint32_t srcSlice,
563                                             MipmapNativeLevel srcLevel,
564                                             MTLOrigin srcOrigin,
565                                             MTLSize srcSize,
566                                             const BufferRef &dst,
567                                             size_t dstOffset,
568                                             size_t dstBytesPerRow,
569                                             size_t dstBytesPerImage,
570                                             MTLBlitOption blitOption);
571 
572     BlitCommandEncoder &copyTexture(const TextureRef &src,
573                                     uint32_t srcSlice,
574                                     MipmapNativeLevel srcLevel,
575                                     const TextureRef &dst,
576                                     uint32_t dstSlice,
577                                     MipmapNativeLevel dstLevel,
578                                     uint32_t sliceCount,
579                                     uint32_t levelCount);
580 
581     BlitCommandEncoder &fillBuffer(const BufferRef &buffer, NSRange range, uint8_t value);
582 
583     BlitCommandEncoder &generateMipmapsForTexture(const TextureRef &texture);
584     BlitCommandEncoder &synchronizeResource(Buffer *bufferPtr);
585     BlitCommandEncoder &synchronizeResource(Texture *texturePtr);
586 
587   private:
get()588     id<MTLBlitCommandEncoder> get()
589     {
590         return static_cast<id<MTLBlitCommandEncoder>>(CommandEncoder::get());
591     }
592 };
593 
594 class ComputeCommandEncoder final : public CommandEncoder
595 {
596   public:
597     ComputeCommandEncoder(CommandBuffer *cmdBuffer);
598     ~ComputeCommandEncoder() override;
599 
600     // Restart the encoder so that new commands can be encoded.
601     // NOTE: parent CommandBuffer's restart() must be called before this.
602     ComputeCommandEncoder &restart();
603 
604     ComputeCommandEncoder &setComputePipelineState(id<MTLComputePipelineState> state);
605 
606     ComputeCommandEncoder &setBuffer(const BufferRef &buffer, uint32_t offset, uint32_t index);
607     ComputeCommandEncoder &setBufferForWrite(const BufferRef &buffer,
608                                              uint32_t offset,
609                                              uint32_t index);
610     ComputeCommandEncoder &setBytes(const uint8_t *bytes, size_t size, uint32_t index);
611     template <typename T>
setData(const T & data,uint32_t index)612     ComputeCommandEncoder &setData(const T &data, uint32_t index)
613     {
614         return setBytes(reinterpret_cast<const uint8_t *>(&data), sizeof(T), index);
615     }
616     ComputeCommandEncoder &setSamplerState(id<MTLSamplerState> state,
617                                            float lodMinClamp,
618                                            float lodMaxClamp,
619                                            uint32_t index);
620     ComputeCommandEncoder &setTexture(const TextureRef &texture, uint32_t index);
621     ComputeCommandEncoder &setTextureForWrite(const TextureRef &texture, uint32_t index);
622 
623     ComputeCommandEncoder &dispatch(const MTLSize &threadGroupsPerGrid,
624                                     const MTLSize &threadsPerGroup);
625 
626     ComputeCommandEncoder &dispatchNonUniform(const MTLSize &threadsPerGrid,
627                                               const MTLSize &threadsPerGroup);
628 
629   private:
get()630     id<MTLComputeCommandEncoder> get()
631     {
632         return static_cast<id<MTLComputeCommandEncoder>>(CommandEncoder::get());
633     }
634 };
635 
636 }  // namespace mtl
637 }  // namespace rx
638 
639 #endif /* LIBANGLE_RENDERER_METAL_COMMANDENBUFFERMTL_H_ */
640