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