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 ©Buffer(const BufferRef &src, 540 size_t srcOffset, 541 const BufferRef &dst, 542 size_t dstOffset, 543 size_t size); 544 545 BlitCommandEncoder ©BufferToTexture(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 ©TextureToBuffer(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 ©Texture(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