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 // ContextMtl.h: 7 // Defines the class interface for ContextMtl, implementing ContextImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ 11 #define LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ 12 13 #import <Metal/Metal.h> 14 15 #include "common/Optional.h" 16 #include "libANGLE/Context.h" 17 #include "libANGLE/renderer/ContextImpl.h" 18 #include "libANGLE/renderer/metal/ProvokingVertexHelper.h" 19 #include "libANGLE/renderer/metal/mtl_buffer_pool.h" 20 #include "libANGLE/renderer/metal/mtl_command_buffer.h" 21 #include "libANGLE/renderer/metal/mtl_occlusion_query_pool.h" 22 #include "libANGLE/renderer/metal/mtl_resources.h" 23 #include "libANGLE/renderer/metal/mtl_state_cache.h" 24 #include "libANGLE/renderer/metal/mtl_utils.h" 25 namespace rx 26 { 27 class DisplayMtl; 28 class FramebufferMtl; 29 class VertexArrayMtl; 30 class ProgramMtl; 31 class RenderTargetMtl; 32 class WindowSurfaceMtl; 33 class TransformFeedbackMtl; 34 35 class ContextMtl : public ContextImpl, public mtl::Context 36 { 37 public: 38 ContextMtl(const gl::State &state, gl::ErrorSet *errorSet, DisplayMtl *display); 39 ~ContextMtl() override; 40 41 angle::Result initialize() override; 42 43 void onDestroy(const gl::Context *context) override; 44 45 // Flush and finish. 46 angle::Result flush(const gl::Context *context) override; 47 angle::Result finish(const gl::Context *context) override; 48 49 // Drawing methods. 50 angle::Result drawArrays(const gl::Context *context, 51 gl::PrimitiveMode mode, 52 GLint first, 53 GLsizei count) override; 54 angle::Result drawArraysInstanced(const gl::Context *context, 55 gl::PrimitiveMode mode, 56 GLint first, 57 GLsizei count, 58 GLsizei instanceCount) override; 59 angle::Result drawArraysInstancedBaseInstance(const gl::Context *context, 60 gl::PrimitiveMode mode, 61 GLint first, 62 GLsizei count, 63 GLsizei instanceCount, 64 GLuint baseInstance) override; 65 66 angle::Result drawElements(const gl::Context *context, 67 gl::PrimitiveMode mode, 68 GLsizei count, 69 gl::DrawElementsType type, 70 const void *indices) override; 71 angle::Result drawElementsBaseVertex(const gl::Context *context, 72 gl::PrimitiveMode mode, 73 GLsizei count, 74 gl::DrawElementsType type, 75 const void *indices, 76 GLint baseVertex) override; 77 angle::Result drawElementsInstanced(const gl::Context *context, 78 gl::PrimitiveMode mode, 79 GLsizei count, 80 gl::DrawElementsType type, 81 const void *indices, 82 GLsizei instanceCount) override; 83 angle::Result drawElementsInstancedBaseVertex(const gl::Context *context, 84 gl::PrimitiveMode mode, 85 GLsizei count, 86 gl::DrawElementsType type, 87 const void *indices, 88 GLsizei instanceCount, 89 GLint baseVertex) override; 90 angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context, 91 gl::PrimitiveMode mode, 92 GLsizei count, 93 gl::DrawElementsType type, 94 const void *indices, 95 GLsizei instances, 96 GLint baseVertex, 97 GLuint baseInstance) override; 98 angle::Result drawRangeElements(const gl::Context *context, 99 gl::PrimitiveMode mode, 100 GLuint start, 101 GLuint end, 102 GLsizei count, 103 gl::DrawElementsType type, 104 const void *indices) override; 105 angle::Result drawRangeElementsBaseVertex(const gl::Context *context, 106 gl::PrimitiveMode mode, 107 GLuint start, 108 GLuint end, 109 GLsizei count, 110 gl::DrawElementsType type, 111 const void *indices, 112 GLint baseVertex) override; 113 angle::Result drawArraysIndirect(const gl::Context *context, 114 gl::PrimitiveMode mode, 115 const void *indirect) override; 116 angle::Result drawElementsIndirect(const gl::Context *context, 117 gl::PrimitiveMode mode, 118 gl::DrawElementsType type, 119 const void *indirect) override; 120 angle::Result multiDrawArrays(const gl::Context *context, 121 gl::PrimitiveMode mode, 122 const GLint *firsts, 123 const GLsizei *counts, 124 GLsizei drawcount) override; 125 angle::Result multiDrawArraysInstanced(const gl::Context *context, 126 gl::PrimitiveMode mode, 127 const GLint *firsts, 128 const GLsizei *counts, 129 const GLsizei *instanceCounts, 130 GLsizei drawcount) override; 131 angle::Result multiDrawArraysIndirect(const gl::Context *context, 132 gl::PrimitiveMode mode, 133 const void *indirect, 134 GLsizei drawcount, 135 GLsizei stride) override; 136 angle::Result multiDrawElements(const gl::Context *context, 137 gl::PrimitiveMode mode, 138 const GLsizei *counts, 139 gl::DrawElementsType type, 140 const GLvoid *const *indices, 141 GLsizei drawcount) override; 142 angle::Result multiDrawElementsInstanced(const gl::Context *context, 143 gl::PrimitiveMode mode, 144 const GLsizei *counts, 145 gl::DrawElementsType type, 146 const GLvoid *const *indices, 147 const GLsizei *instanceCounts, 148 GLsizei drawcount) override; 149 angle::Result multiDrawElementsIndirect(const gl::Context *context, 150 gl::PrimitiveMode mode, 151 gl::DrawElementsType type, 152 const void *indirect, 153 GLsizei drawcount, 154 GLsizei stride) override; 155 angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context, 156 gl::PrimitiveMode mode, 157 const GLint *firsts, 158 const GLsizei *counts, 159 const GLsizei *instanceCounts, 160 const GLuint *baseInstances, 161 GLsizei drawcount) override; 162 angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context *context, 163 gl::PrimitiveMode mode, 164 const GLsizei *counts, 165 gl::DrawElementsType type, 166 const GLvoid *const *indices, 167 const GLsizei *instanceCounts, 168 const GLint *baseVertices, 169 const GLuint *baseInstances, 170 GLsizei drawcount) override; 171 // Device loss 172 gl::GraphicsResetStatus getResetStatus() override; 173 174 // EXT_debug_marker 175 angle::Result insertEventMarker(GLsizei length, const char *marker) override; 176 angle::Result pushGroupMarker(GLsizei length, const char *marker) override; 177 angle::Result popGroupMarker() override; 178 179 // KHR_debug 180 angle::Result pushDebugGroup(const gl::Context *context, 181 GLenum source, 182 GLuint id, 183 const std::string &message) override; 184 angle::Result popDebugGroup(const gl::Context *context) override; 185 186 // State sync with dirty bits. 187 angle::Result syncState(const gl::Context *context, 188 const gl::State::DirtyBits &dirtyBits, 189 const gl::State::DirtyBits &bitMask, 190 gl::Command command) override; 191 192 // Disjoint timer queries 193 GLint getGPUDisjoint() override; 194 GLint64 getTimestamp() override; 195 196 // Context switching 197 angle::Result onMakeCurrent(const gl::Context *context) override; 198 angle::Result onUnMakeCurrent(const gl::Context *context) override; 199 200 // Native capabilities, unmodified by gl::Context. 201 gl::Caps getNativeCaps() const override; 202 const gl::TextureCapsMap &getNativeTextureCaps() const override; 203 const gl::Extensions &getNativeExtensions() const override; 204 const gl::Limitations &getNativeLimitations() const override; 205 getProgram()206 const ProgramMtl *getProgram() const { return mProgram; } 207 208 // Shader creation 209 CompilerImpl *createCompiler() override; 210 ShaderImpl *createShader(const gl::ShaderState &state) override; 211 ProgramImpl *createProgram(const gl::ProgramState &state) override; 212 213 // Framebuffer creation 214 FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override; 215 216 // Texture creation 217 TextureImpl *createTexture(const gl::TextureState &state) override; 218 219 // Renderbuffer creation 220 RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override; 221 222 // Buffer creation 223 BufferImpl *createBuffer(const gl::BufferState &state) override; 224 225 // Vertex Array creation 226 VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override; 227 228 // Query and Fence creation 229 QueryImpl *createQuery(gl::QueryType type) override; 230 FenceNVImpl *createFenceNV() override; 231 SyncImpl *createSync() override; 232 233 // Transform Feedback creation 234 TransformFeedbackImpl *createTransformFeedback( 235 const gl::TransformFeedbackState &state) override; 236 237 // Sampler object creation 238 SamplerImpl *createSampler(const gl::SamplerState &state) override; 239 240 // Program Pipeline object creation 241 ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override; 242 243 // Memory object creation. 244 MemoryObjectImpl *createMemoryObject() override; 245 246 // Semaphore creation. 247 SemaphoreImpl *createSemaphore() override; 248 249 // Overlay creation. 250 OverlayImpl *createOverlay(const gl::OverlayState &state) override; 251 252 angle::Result dispatchCompute(const gl::Context *context, 253 GLuint numGroupsX, 254 GLuint numGroupsY, 255 GLuint numGroupsZ) override; 256 angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override; 257 258 angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override; 259 angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override; 260 261 // override mtl::ErrorHandler 262 void handleError(GLenum error, 263 const char *file, 264 const char *function, 265 unsigned int line) override; 266 void handleError(NSError *_Nullable error, 267 const char *file, 268 const char *function, 269 unsigned int line) override; 270 271 using ContextImpl::handleError; 272 273 void invalidateState(const gl::Context *context); 274 void invalidateDefaultAttribute(size_t attribIndex); 275 void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask); 276 void invalidateCurrentTextures(); 277 void invalidateDriverUniforms(); 278 void invalidateRenderPipeline(); 279 280 // Call this to notify ContextMtl whenever FramebufferMtl's state changed 281 void onDrawFrameBufferChangedState(const gl::Context *context, 282 FramebufferMtl *framebuffer, 283 bool renderPassChanged); 284 void onBackbufferResized(const gl::Context *context, WindowSurfaceMtl *backbuffer); 285 286 // Invoke by QueryMtl 287 angle::Result onOcclusionQueryBegin(const gl::Context *context, QueryMtl *query); 288 void onOcclusionQueryEnd(const gl::Context *context, QueryMtl *query); 289 void onOcclusionQueryDestroy(const gl::Context *context, QueryMtl *query); 290 291 // Useful for temporarily pause then restart occlusion query during clear/blit with draw. hasActiveOcclusionQuery()292 bool hasActiveOcclusionQuery() const { return mOcclusionQuery; } 293 // Disable the occlusion query in the current render pass. 294 // The render pass must already started. 295 void disableActiveOcclusionQueryInRenderPass(); 296 // Re-enable the occlusion query in the current render pass. 297 // The render pass must already started. 298 // NOTE: the old query's result will be retained and combined with the new result. 299 angle::Result restartActiveOcclusionQueryInRenderPass(); 300 301 // Invoke by TransformFeedbackMtl 302 void onTransformFeedbackActive(const gl::Context *context, TransformFeedbackMtl *xfb); 303 void onTransformFeedbackInactive(const gl::Context *context, TransformFeedbackMtl *xfb); 304 305 // Invoke by mtl::Sync 306 void queueEventSignal(const mtl::SharedEventRef &event, uint64_t value); 307 void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value); 308 309 const mtl::ClearColorValue &getClearColorValue() const; 310 const mtl::WriteMaskArray &getWriteMaskArray() const; 311 float getClearDepthValue() const; 312 uint32_t getClearStencilValue() const; 313 // Return front facing stencil write mask 314 uint32_t getStencilMask() const; 315 bool getDepthMask() const; 316 317 const mtl::Format &getPixelFormat(angle::FormatID angleFormatId) const; 318 const mtl::FormatCaps &getNativeFormatCaps(MTLPixelFormat mtlFormat) const; 319 // See mtl::FormatTable::getVertexFormat() 320 const mtl::VertexFormat &getVertexFormat(angle::FormatID angleFormatId, 321 bool tightlyPacked) const; 322 323 angle::Result getIncompleteTexture(const gl::Context *context, 324 gl::TextureType type, 325 gl::Texture **textureOut); 326 327 // Recommended to call these methods to end encoding instead of invoking the encoder's 328 // endEncoding() directly. 329 void endRenderEncoding(mtl::RenderCommandEncoder *encoder); 330 // Ends any active command encoder 331 void endEncoding(bool forceSaveRenderPassContent); 332 333 void flushCommandBuffer(mtl::CommandBufferFinishOperation operation); 334 void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable); 335 angle::Result finishCommandBuffer(); 336 337 // Check whether compatible render pass has been started. Compatible render pass is a render 338 // pass having the same attachments, and possibly having different load/store options. 339 bool hasStartedRenderPass(const mtl::RenderPassDesc &desc); 340 341 // Get current render encoder. May be nullptr if no render pass has been started. 342 mtl::RenderCommandEncoder *getRenderCommandEncoder(); 343 344 // Will end current command encoder if it is valid, then start new encoder. 345 // Unless hasStartedRenderPass(desc) returns true. 346 // Note: passing a compatible render pass with different load/store options won't end the 347 // current render pass. If a new render pass is desired, call endEncoding() prior to this. 348 mtl::RenderCommandEncoder *getRenderPassCommandEncoder(const mtl::RenderPassDesc &desc); 349 350 // Utilities to quickly create render command encoder to a specific texture: 351 // The previous content of texture will be loaded 352 mtl::RenderCommandEncoder *getTextureRenderCommandEncoder(const mtl::TextureRef &textureTarget, 353 const mtl::ImageNativeIndex &index); 354 // The previous content of texture will be loaded if clearColor is not provided 355 mtl::RenderCommandEncoder *getRenderTargetCommandEncoderWithClear( 356 const RenderTargetMtl &renderTarget, 357 const Optional<MTLClearColor> &clearColor); 358 // The previous content of texture will be loaded 359 mtl::RenderCommandEncoder *getRenderTargetCommandEncoder(const RenderTargetMtl &renderTarget); 360 361 // Will end current command encoder and start new blit command encoder. Unless a blit comamnd 362 // encoder is already started. 363 mtl::BlitCommandEncoder *getBlitCommandEncoder(); 364 365 // Will end current command encoder and start new compute command encoder. Unless a compute 366 // command encoder is already started. 367 mtl::ComputeCommandEncoder *getComputeCommandEncoder(); 368 369 // Get the provoking vertex command encoder. 370 mtl::ComputeCommandEncoder *getIndexPreprocessingCommandEncoder(); 371 372 private: 373 void ensureCommandBufferReady(); 374 angle::Result ensureIncompleteTexturesCreated(const gl::Context *context); 375 angle::Result setupDraw(const gl::Context *context, 376 gl::PrimitiveMode mode, 377 GLint firstVertex, 378 GLsizei vertexOrIndexCount, 379 GLsizei instanceCount, 380 gl::DrawElementsType indexTypeOrNone, 381 const void *indices, 382 bool xfbPass); 383 384 angle::Result setupDrawImpl(const gl::Context *context, 385 gl::PrimitiveMode mode, 386 GLint firstVertex, 387 GLsizei vertexOrIndexCount, 388 GLsizei instanceCount, 389 gl::DrawElementsType indexTypeOrNone, 390 const void *indices, 391 bool xfbPass); 392 393 angle::Result drawTriFanArrays(const gl::Context *context, 394 GLint first, 395 GLsizei count, 396 GLsizei instances); 397 angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context, 398 GLint first, 399 GLsizei count, 400 GLsizei instances); 401 angle::Result drawTriFanArraysLegacy(const gl::Context *context, 402 GLint first, 403 GLsizei count, 404 GLsizei instances); 405 angle::Result drawTriFanElements(const gl::Context *context, 406 GLsizei count, 407 gl::DrawElementsType type, 408 const void *indices, 409 GLsizei instances); 410 411 angle::Result drawLineLoopArraysNonInstanced(const gl::Context *context, 412 GLint first, 413 GLsizei count); 414 angle::Result drawLineLoopArrays(const gl::Context *context, 415 GLint first, 416 GLsizei count, 417 GLsizei instances); 418 angle::Result drawLineLoopElementsNonInstancedNoPrimitiveRestart(const gl::Context *context, 419 GLsizei count, 420 gl::DrawElementsType type, 421 const void *indices); 422 angle::Result drawLineLoopElements(const gl::Context *context, 423 GLsizei count, 424 gl::DrawElementsType type, 425 const void *indices, 426 GLsizei instances); 427 428 angle::Result drawArraysImpl(const gl::Context *context, 429 gl::PrimitiveMode mode, 430 GLint first, 431 GLsizei count, 432 GLsizei instanceCount); 433 434 angle::Result drawElementsImpl(const gl::Context *context, 435 gl::PrimitiveMode mode, 436 GLsizei count, 437 gl::DrawElementsType type, 438 const void *indices, 439 GLsizei instanceCount); 440 441 void updateExtendedState(const gl::State &glState); 442 443 void updateViewport(FramebufferMtl *framebufferMtl, 444 const gl::Rectangle &viewport, 445 float nearPlane, 446 float farPlane); 447 void updateDepthRange(float nearPlane, float farPlane); 448 void updateBlendDescArray(const gl::BlendStateExt &blendStateExt); 449 void updateScissor(const gl::State &glState); 450 void updateCullMode(const gl::State &glState); 451 void updateFrontFace(const gl::State &glState); 452 void updateDepthBias(const gl::State &glState); 453 void updateDrawFrameBufferBinding(const gl::Context *context); 454 void updateProgramExecutable(const gl::Context *context); 455 void updateVertexArray(const gl::Context *context); 456 bool requiresIndexRewrite(const gl::State &state, gl::PrimitiveMode mode); 457 angle::Result updateDefaultAttribute(size_t attribIndex); 458 void filterOutXFBOnlyDirtyBits(const gl::Context *context); 459 angle::Result handleDirtyActiveTextures(const gl::Context *context); 460 angle::Result handleDirtyDefaultAttribs(const gl::Context *context); 461 angle::Result handleDirtyDriverUniforms(const gl::Context *context, 462 GLint drawCallFirstVertex, 463 uint32_t verticesPerInstance); 464 angle::Result fillDriverXFBUniforms(GLint drawCallFirstVertex, 465 uint32_t verticesPerInstance, 466 uint32_t skippedInstances); 467 angle::Result handleDirtyDepthStencilState(const gl::Context *context); 468 angle::Result handleDirtyDepthBias(const gl::Context *context); 469 angle::Result handleDirtyRenderPass(const gl::Context *context); 470 angle::Result checkIfPipelineChanged(const gl::Context *context, 471 gl::PrimitiveMode primitiveMode, 472 bool xfbPass, 473 bool *pipelineDescChanged); 474 475 angle::Result startOcclusionQueryInRenderPass(QueryMtl *query, bool clearOldValue); 476 477 // Dirty bits. 478 enum DirtyBitType : size_t 479 { 480 DIRTY_BIT_DEFAULT_ATTRIBS, 481 DIRTY_BIT_TEXTURES, 482 DIRTY_BIT_DRIVER_UNIFORMS, 483 DIRTY_BIT_DEPTH_STENCIL_DESC, 484 DIRTY_BIT_DEPTH_BIAS, 485 DIRTY_BIT_STENCIL_REF, 486 DIRTY_BIT_BLEND_COLOR, 487 DIRTY_BIT_VIEWPORT, 488 DIRTY_BIT_SCISSOR, 489 DIRTY_BIT_DRAW_FRAMEBUFFER, 490 DIRTY_BIT_CULL_MODE, 491 DIRTY_BIT_WINDING, 492 DIRTY_BIT_RENDER_PIPELINE, 493 DIRTY_BIT_UNIFORM_BUFFERS_BINDING, 494 DIRTY_BIT_RASTERIZER_DISCARD, 495 496 DIRTY_BIT_INVALID, 497 DIRTY_BIT_MAX = DIRTY_BIT_INVALID, 498 }; 499 500 // Must keep this in sync with DriverUniformExtended::createUniformFields in: 501 // src/compiler/translator/tree_util/DriverUniform.h 502 struct DriverUniforms 503 { 504 float viewport[4]; 505 506 // 32 bits for 32 clip distances 507 uint32_t enabledClipDistances; 508 509 uint32_t xfbActiveUnpaused; 510 int32_t xfbVerticesPerInstance; 511 512 int32_t numSamples; 513 514 int32_t xfbBufferOffsets[4]; 515 uint32_t acbBufferOffsets[4]; 516 517 // We'll use x, y, z, w for near / far / diff / zscale respectively. 518 float depthRange[4]; 519 520 // Metal specific 521 float halfRenderArea[2]; 522 float flipXY[2]; 523 float negFlipXY[2]; 524 uint32_t emulatedInstanceID; 525 uint32_t coverageMask; 526 }; 527 528 struct DefaultAttribute 529 { 530 uint8_t values[sizeof(float) * 4]; 531 }; 532 533 mtl::OcclusionQueryPool mOcclusionQueryPool; 534 535 mtl::CommandBuffer mCmdBuffer; 536 mtl::RenderCommandEncoder mRenderEncoder; 537 mtl::BlitCommandEncoder mBlitEncoder; 538 mtl::ComputeCommandEncoder mComputeEncoder; 539 540 // Cached back-end objects 541 FramebufferMtl *mDrawFramebuffer = nullptr; 542 VertexArrayMtl *mVertexArray = nullptr; 543 ProgramMtl *mProgram = nullptr; 544 QueryMtl *mOcclusionQuery = nullptr; 545 546 using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; 547 548 gl::AttributesMask mDirtyDefaultAttribsMask; 549 DirtyBits mDirtyBits; 550 551 // State 552 mtl::RenderPipelineDesc mRenderPipelineDesc; 553 mtl::DepthStencilDesc mDepthStencilDesc; 554 mtl::BlendDescArray mBlendDescArray; 555 mtl::WriteMaskArray mWriteMaskArray; 556 mtl::ClearColorValue mClearColor; 557 uint32_t mClearStencil = 0; 558 uint32_t mStencilRefFront = 0; 559 uint32_t mStencilRefBack = 0; 560 MTLViewport mViewport; 561 MTLScissorRect mScissorRect; 562 MTLWinding mWinding; 563 MTLCullMode mCullMode; 564 bool mCullAllPolygons = false; 565 566 // Lineloop and TriFan index buffer 567 mtl::BufferPool mLineLoopIndexBuffer; 568 mtl::BufferPool mLineLoopLastSegmentIndexBuffer; 569 mtl::BufferPool mTriFanIndexBuffer; 570 // one buffer can be reused for any starting vertex in DrawArrays() 571 mtl::BufferRef mTriFanArraysIndexBuffer; 572 573 // Dummy texture to be used for transform feedback only pass. 574 mtl::TextureRef mDummyXFBRenderTexture; 575 576 DriverUniforms mDriverUniforms; 577 578 DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs]; 579 580 IncompleteTextureSet mIncompleteTextures; 581 bool mIncompleteTexturesInitialized = false; 582 ProvokingVertexHelper mProvokingVertexHelper; 583 }; 584 585 } // namespace rx 586 587 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */ 588