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