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 ©Buffer(const BufferRef &src, 545 size_t srcOffset, 546 const BufferRef &dst, 547 size_t dstOffset, 548 size_t size); 549 550 BlitCommandEncoder ©BufferToTexture(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 ©TextureToBuffer(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 ©Texture(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