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_resources.h" 21 #include "libANGLE/renderer/metal/mtl_state_cache.h" 22 #include "libANGLE/renderer/metal/mtl_utils.h" 23 24 namespace rx 25 { 26 class DisplayMtl; 27 class FramebufferMtl; 28 class VertexArrayMtl; 29 class ProgramMtl; 30 31 class ContextMtl : public ContextImpl, public mtl::Context 32 { 33 public: 34 ContextMtl(const gl::State &state, gl::ErrorSet *errorSet, DisplayMtl *display); 35 ~ContextMtl() override; 36 37 angle::Result initialize() override; 38 39 void onDestroy(const gl::Context *context) override; 40 41 // Flush and finish. 42 angle::Result flush(const gl::Context *context) override; 43 angle::Result finish(const gl::Context *context) override; 44 45 // Drawing methods. 46 angle::Result drawArrays(const gl::Context *context, 47 gl::PrimitiveMode mode, 48 GLint first, 49 GLsizei count) override; 50 angle::Result drawArraysInstanced(const gl::Context *context, 51 gl::PrimitiveMode mode, 52 GLint first, 53 GLsizei count, 54 GLsizei instanceCount) override; 55 angle::Result drawArraysInstancedBaseInstance(const gl::Context *context, 56 gl::PrimitiveMode mode, 57 GLint first, 58 GLsizei count, 59 GLsizei instanceCount, 60 GLuint baseInstance) override; 61 62 angle::Result drawElements(const gl::Context *context, 63 gl::PrimitiveMode mode, 64 GLsizei count, 65 gl::DrawElementsType type, 66 const void *indices) override; 67 angle::Result drawElementsBaseVertex(const gl::Context *context, 68 gl::PrimitiveMode mode, 69 GLsizei count, 70 gl::DrawElementsType type, 71 const void *indices, 72 GLint baseVertex) override; 73 angle::Result drawElementsInstanced(const gl::Context *context, 74 gl::PrimitiveMode mode, 75 GLsizei count, 76 gl::DrawElementsType type, 77 const void *indices, 78 GLsizei instanceCount) override; 79 angle::Result drawElementsInstancedBaseVertex(const gl::Context *context, 80 gl::PrimitiveMode mode, 81 GLsizei count, 82 gl::DrawElementsType type, 83 const void *indices, 84 GLsizei instanceCount, 85 GLint baseVertex) override; 86 angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context, 87 gl::PrimitiveMode mode, 88 GLsizei count, 89 gl::DrawElementsType type, 90 const void *indices, 91 GLsizei instances, 92 GLint baseVertex, 93 GLuint baseInstance) override; 94 angle::Result drawRangeElements(const gl::Context *context, 95 gl::PrimitiveMode mode, 96 GLuint start, 97 GLuint end, 98 GLsizei count, 99 gl::DrawElementsType type, 100 const void *indices) override; 101 angle::Result drawRangeElementsBaseVertex(const gl::Context *context, 102 gl::PrimitiveMode mode, 103 GLuint start, 104 GLuint end, 105 GLsizei count, 106 gl::DrawElementsType type, 107 const void *indices, 108 GLint baseVertex) override; 109 angle::Result drawArraysIndirect(const gl::Context *context, 110 gl::PrimitiveMode mode, 111 const void *indirect) override; 112 angle::Result drawElementsIndirect(const gl::Context *context, 113 gl::PrimitiveMode mode, 114 gl::DrawElementsType type, 115 const void *indirect) override; 116 117 // Device loss 118 gl::GraphicsResetStatus getResetStatus() override; 119 120 // Vendor and description strings. 121 std::string getVendorString() const override; 122 std::string getRendererDescription() const override; 123 124 // EXT_debug_marker 125 angle::Result insertEventMarker(GLsizei length, const char *marker) override; 126 angle::Result pushGroupMarker(GLsizei length, const char *marker) override; 127 angle::Result popGroupMarker() override; 128 129 // KHR_debug 130 angle::Result pushDebugGroup(const gl::Context *context, 131 GLenum source, 132 GLuint id, 133 const std::string &message) override; 134 angle::Result popDebugGroup(const gl::Context *context) override; 135 136 // State sync with dirty bits. 137 angle::Result syncState(const gl::Context *context, 138 const gl::State::DirtyBits &dirtyBits, 139 const gl::State::DirtyBits &bitMask) override; 140 141 // Disjoint timer queries 142 GLint getGPUDisjoint() override; 143 GLint64 getTimestamp() override; 144 145 // Context switching 146 angle::Result onMakeCurrent(const gl::Context *context) override; 147 angle::Result onUnMakeCurrent(const gl::Context *context) override; 148 149 // Native capabilities, unmodified by gl::Context. 150 gl::Caps getNativeCaps() const override; 151 const gl::TextureCapsMap &getNativeTextureCaps() const override; 152 const gl::Extensions &getNativeExtensions() const override; 153 const gl::Limitations &getNativeLimitations() const override; 154 155 // Shader creation 156 CompilerImpl *createCompiler() override; 157 ShaderImpl *createShader(const gl::ShaderState &state) override; 158 ProgramImpl *createProgram(const gl::ProgramState &state) override; 159 160 // Framebuffer creation 161 FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override; 162 163 // Texture creation 164 TextureImpl *createTexture(const gl::TextureState &state) override; 165 166 // Renderbuffer creation 167 RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override; 168 169 // Buffer creation 170 BufferImpl *createBuffer(const gl::BufferState &state) override; 171 172 // Vertex Array creation 173 VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override; 174 175 // Query and Fence creation 176 QueryImpl *createQuery(gl::QueryType type) override; 177 FenceNVImpl *createFenceNV() override; 178 SyncImpl *createSync() override; 179 180 // Transform Feedback creation 181 TransformFeedbackImpl *createTransformFeedback( 182 const gl::TransformFeedbackState &state) override; 183 184 // Sampler object creation 185 SamplerImpl *createSampler(const gl::SamplerState &state) override; 186 187 // Program Pipeline object creation 188 ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override; 189 190 // Memory object creation. 191 MemoryObjectImpl *createMemoryObject() override; 192 193 // Semaphore creation. 194 SemaphoreImpl *createSemaphore() override; 195 196 // Overlay creation. 197 OverlayImpl *createOverlay(const gl::OverlayState &state) override; 198 199 angle::Result dispatchCompute(const gl::Context *context, 200 GLuint numGroupsX, 201 GLuint numGroupsY, 202 GLuint numGroupsZ) override; 203 angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override; 204 205 angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override; 206 angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override; 207 208 // override mtl::ErrorHandler 209 void handleError(GLenum error, 210 const char *file, 211 const char *function, 212 unsigned int line) override; 213 void handleError(NSError *_Nullable error, 214 const char *file, 215 const char *function, 216 unsigned int line) override; 217 218 using ContextImpl::handleError; 219 220 void invalidateState(const gl::Context *context); 221 void invalidateDefaultAttribute(size_t attribIndex); 222 void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask); 223 void invalidateCurrentTextures(); 224 void invalidateDriverUniforms(); 225 void invalidateRenderPipeline(); 226 227 // Call this to notify ContextMtl whenever FramebufferMtl's state changed 228 void onDrawFrameBufferChange(const gl::Context *context, FramebufferMtl *framebuffer); 229 230 const MTLClearColor &getClearColorValue() const; 231 MTLColorWriteMask getColorMask() const; 232 float getClearDepthValue() const; 233 uint32_t getClearStencilValue() const; 234 // Return front facing stencil write mask 235 uint32_t getStencilMask() const; 236 bool getDepthMask() const; 237 238 const mtl::Format &getPixelFormat(angle::FormatID angleFormatId) const; 239 // See mtl::FormatTable::getVertexFormat() 240 const mtl::VertexFormat &getVertexFormat(angle::FormatID angleFormatId, 241 bool tightlyPacked) const; 242 243 angle::Result getIncompleteTexture(const gl::Context *context, 244 gl::TextureType type, 245 gl::Texture **textureOut); 246 247 // Recommended to call these methods to end encoding instead of invoking the encoder's 248 // endEncoding() directly. 249 void endEncoding(mtl::RenderCommandEncoder *encoder); 250 // Ends any active command encoder 251 void endEncoding(bool forceSaveRenderPassContent); 252 253 void flushCommandBufer(); 254 void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable); 255 angle::Result finishCommandBuffer(); 256 257 // Check whether compatible render pass has been started. 258 bool hasStartedRenderPass(const mtl::RenderPassDesc &desc); 259 bool hasStartedRenderPass(FramebufferMtl *framebuffer); 260 261 // Get current render encoder. May be nullptr if no render pass has been started. 262 mtl::RenderCommandEncoder *getRenderCommandEncoder(); 263 264 mtl::RenderCommandEncoder *getCurrentFramebufferRenderCommandEncoder(); 265 266 // Will end current command encoder if it is valid, then start new encoder. 267 // Unless hasStartedRenderPass(desc) returns true. 268 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::RenderPassDesc &desc); 269 270 // Utilities to quickly create render command enconder to a specific texture: 271 // The previous content of texture will be loaded if clearColor is not provided 272 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget, 273 const gl::ImageIndex &index, 274 const Optional<MTLClearColor> &clearColor); 275 // The previous content of texture will be loaded 276 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget, 277 const gl::ImageIndex &index); 278 279 // Will end current command encoder and start new blit command encoder. Unless a blit comamnd 280 // encoder is already started. 281 mtl::BlitCommandEncoder *getBlitCommandEncoder(); 282 283 // Will end current command encoder and start new compute command encoder. Unless a compute 284 // command encoder is already started. 285 mtl::ComputeCommandEncoder *getComputeCommandEncoder(); 286 287 private: 288 void ensureCommandBufferValid(); 289 angle::Result ensureIncompleteTexturesCreated(const gl::Context *context); 290 angle::Result setupDraw(const gl::Context *context, 291 gl::PrimitiveMode mode, 292 GLint firstVertex, 293 GLsizei vertexOrIndexCount, 294 GLsizei instanceCount, 295 gl::DrawElementsType indexTypeOrNone, 296 const void *indices); 297 angle::Result genLineLoopLastSegment(const gl::Context *context, 298 GLint firstVertex, 299 GLsizei vertexOrIndexCount, 300 GLsizei instanceCount, 301 gl::DrawElementsType indexTypeOrNone, 302 const void *indices, 303 mtl::BufferRef *lastSegmentIndexBufferOut); 304 305 angle::Result drawTriFanArrays(const gl::Context *context, 306 GLint first, 307 GLsizei count, 308 GLsizei instances); 309 angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context, 310 GLint first, 311 GLsizei count, 312 GLsizei instances); 313 angle::Result drawTriFanArraysLegacy(const gl::Context *context, 314 GLint first, 315 GLsizei count, 316 GLsizei instances); 317 angle::Result drawTriFanElements(const gl::Context *context, 318 GLsizei count, 319 gl::DrawElementsType type, 320 const void *indices, 321 GLsizei instances); 322 323 angle::Result drawArraysImpl(const gl::Context *context, 324 gl::PrimitiveMode mode, 325 GLint first, 326 GLsizei count, 327 GLsizei instanceCount); 328 329 angle::Result drawElementsImpl(const gl::Context *context, 330 gl::PrimitiveMode mode, 331 GLsizei count, 332 gl::DrawElementsType type, 333 const void *indices, 334 GLsizei instanceCount); 335 336 void updateExtendedState(const gl::State &glState); 337 338 void updateViewport(FramebufferMtl *framebufferMtl, 339 const gl::Rectangle &viewport, 340 float nearPlane, 341 float farPlane); 342 void updateDepthRange(float nearPlane, float farPlane); 343 void updateScissor(const gl::State &glState); 344 void updateCullMode(const gl::State &glState); 345 void updateFrontFace(const gl::State &glState); 346 void updateDepthBias(const gl::State &glState); 347 void updateDrawFrameBufferBinding(const gl::Context *context); 348 void updateProgramExecutable(const gl::Context *context); 349 void updateVertexArray(const gl::Context *context); 350 351 angle::Result updateDefaultAttribute(size_t attribIndex); 352 angle::Result handleDirtyActiveTextures(const gl::Context *context); 353 angle::Result handleDirtyDefaultAttribs(const gl::Context *context); 354 angle::Result handleDirtyDriverUniforms(const gl::Context *context); 355 angle::Result handleDirtyDepthStencilState(const gl::Context *context); 356 angle::Result handleDirtyDepthBias(const gl::Context *context); 357 angle::Result checkIfPipelineChanged(const gl::Context *context, 358 gl::PrimitiveMode primitiveMode, 359 Optional<mtl::RenderPipelineDesc> *changedPipelineDesc); 360 361 // Dirty bits. 362 enum DirtyBitType : size_t 363 { 364 DIRTY_BIT_DEFAULT_ATTRIBS, 365 DIRTY_BIT_TEXTURES, 366 DIRTY_BIT_DRIVER_UNIFORMS, 367 DIRTY_BIT_DEPTH_STENCIL_DESC, 368 DIRTY_BIT_DEPTH_BIAS, 369 DIRTY_BIT_STENCIL_REF, 370 DIRTY_BIT_BLEND_COLOR, 371 DIRTY_BIT_VIEWPORT, 372 DIRTY_BIT_SCISSOR, 373 DIRTY_BIT_DRAW_FRAMEBUFFER, 374 DIRTY_BIT_CULL_MODE, 375 DIRTY_BIT_WINDING, 376 DIRTY_BIT_RENDER_PIPELINE, 377 DIRTY_BIT_MAX, 378 }; 379 380 // See compiler/translator/TranslatorVulkan.cpp: AddDriverUniformsToShader() 381 struct DriverUniforms 382 { 383 float viewport[4]; 384 385 float halfRenderArea[2]; 386 float flipXY[2]; 387 float negFlipXY[2]; 388 389 // 32 bits for 32 clip distances 390 uint32_t enabledClipDistances; 391 392 // NOTE(hqle): Transform feedsback is not supported yet. 393 uint32_t xfbActiveUnpaused; 394 uint32_t xfbVerticesPerDraw; 395 // NOTE: Explicit padding. Fill in with useful data when needed in the future. 396 int32_t padding[3]; 397 398 int32_t xfbBufferOffsets[4]; 399 uint32_t acbBufferOffsets[4]; 400 401 // We'll use x, y, z, w for near / far / diff / zscale respectively. 402 float depthRange[4]; 403 404 // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is 405 // padded to the size of two vec4's). 406 float preRotation[8]; 407 408 // Used to pre-rotate gl_FragCoord for Vulkan swapchain images on Android (a mat2, which is 409 // padded to the size of two vec4's). 410 float fragRotation[8]; 411 }; 412 413 struct DefaultAttribute 414 { 415 // NOTE(hqle): Support integer default attributes in ES 3.0 416 float values[4]; 417 }; 418 419 mtl::CommandBuffer mCmdBuffer; 420 mtl::RenderCommandEncoder mRenderEncoder; 421 mtl::BlitCommandEncoder mBlitEncoder; 422 mtl::ComputeCommandEncoder mComputeEncoder; 423 424 // Cached back-end objects 425 FramebufferMtl *mDrawFramebuffer = nullptr; 426 VertexArrayMtl *mVertexArray = nullptr; 427 ProgramMtl *mProgram = nullptr; 428 429 // Special flag to indicate current draw framebuffer is default framebuffer. 430 // We need this instead of calling mDrawFramebuffer->getState().isDefault() because 431 // mDrawFramebuffer might point to a deleted object, ContextMtl only knows about this very late, 432 // only during syncState() function call. 433 bool mDrawFramebufferIsDefault = true; 434 435 using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; 436 437 gl::AttributesMask mDirtyDefaultAttribsMask; 438 DirtyBits mDirtyBits; 439 440 // State 441 mtl::RenderPipelineDesc mRenderPipelineDesc; 442 mtl::DepthStencilDesc mDepthStencilDesc; 443 mtl::BlendDesc mBlendDesc; 444 MTLClearColor mClearColor; 445 uint32_t mClearStencil = 0; 446 uint32_t mStencilRefFront = 0; 447 uint32_t mStencilRefBack = 0; 448 MTLViewport mViewport; 449 MTLScissorRect mScissorRect; 450 MTLWinding mWinding; 451 MTLCullMode mCullMode; 452 bool mCullAllPolygons = false; 453 454 // Lineloop and TriFan index buffer 455 mtl::BufferPool mLineLoopIndexBuffer; 456 mtl::BufferPool mTriFanIndexBuffer; 457 // one buffer can be reused for any starting vertex in DrawArrays() 458 mtl::BufferRef mTriFanArraysIndexBuffer; 459 460 DriverUniforms mDriverUniforms; 461 462 DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs]; 463 464 IncompleteTextureSet mIncompleteTextures; 465 bool mIncompleteTexturesInitialized = false; 466 }; 467 468 } // namespace rx 469 470 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */ 471