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