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