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 // Recommended to call these methods to end encoding instead of invoking the encoder's 244 // endEncoding() directly. 245 void endEncoding(mtl::RenderCommandEncoder *encoder); 246 // Ends any active command encoder 247 void endEncoding(bool forceSaveRenderPassContent); 248 249 void flushCommandBufer(); 250 void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable); 251 angle::Result finishCommandBuffer(); 252 253 // Check whether compatible render pass has been started. 254 bool hasStartedRenderPass(const mtl::RenderPassDesc &desc); 255 bool hasStartedRenderPass(FramebufferMtl *framebuffer); 256 257 // Get current render encoder. May be nullptr if no render pass has been started. 258 mtl::RenderCommandEncoder *getRenderCommandEncoder(); 259 260 mtl::RenderCommandEncoder *getCurrentFramebufferRenderCommandEncoder(); 261 262 // Will end current command encoder if it is valid, then start new encoder. 263 // Unless hasStartedRenderPass(desc) returns true. 264 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::RenderPassDesc &desc); 265 266 // Utilities to quickly create render command enconder to a specific texture: 267 // The previous content of texture will be loaded if clearColor is not provided 268 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget, 269 const gl::ImageIndex &index, 270 const Optional<MTLClearColor> &clearColor); 271 // The previous content of texture will be loaded 272 mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget, 273 const gl::ImageIndex &index); 274 275 // Will end current command encoder and start new blit command encoder. Unless a blit comamnd 276 // encoder is already started. 277 mtl::BlitCommandEncoder *getBlitCommandEncoder(); 278 279 // Will end current command encoder and start new compute command encoder. Unless a compute 280 // command encoder is already started. 281 mtl::ComputeCommandEncoder *getComputeCommandEncoder(); 282 283 private: 284 void ensureCommandBufferValid(); 285 angle::Result setupDraw(const gl::Context *context, 286 gl::PrimitiveMode mode, 287 GLint firstVertex, 288 GLsizei vertexOrIndexCount, 289 GLsizei instanceCount, 290 gl::DrawElementsType indexTypeOrNone, 291 const void *indices); 292 angle::Result genLineLoopLastSegment(const gl::Context *context, 293 GLint firstVertex, 294 GLsizei vertexOrIndexCount, 295 GLsizei instanceCount, 296 gl::DrawElementsType indexTypeOrNone, 297 const void *indices, 298 mtl::BufferRef *lastSegmentIndexBufferOut); 299 300 angle::Result drawTriFanArrays(const gl::Context *context, 301 GLint first, 302 GLsizei count, 303 GLsizei instances); 304 angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context, 305 GLint first, 306 GLsizei count, 307 GLsizei instances); 308 angle::Result drawTriFanArraysLegacy(const gl::Context *context, 309 GLint first, 310 GLsizei count, 311 GLsizei instances); 312 angle::Result drawTriFanElements(const gl::Context *context, 313 GLsizei count, 314 gl::DrawElementsType type, 315 const void *indices, 316 GLsizei instances); 317 318 angle::Result drawArraysImpl(const gl::Context *context, 319 gl::PrimitiveMode mode, 320 GLint first, 321 GLsizei count, 322 GLsizei instanceCount); 323 324 angle::Result drawElementsImpl(const gl::Context *context, 325 gl::PrimitiveMode mode, 326 GLsizei count, 327 gl::DrawElementsType type, 328 const void *indices, 329 GLsizei instanceCount); 330 331 void updateViewport(FramebufferMtl *framebufferMtl, 332 const gl::Rectangle &viewport, 333 float nearPlane, 334 float farPlane); 335 void updateDepthRange(float nearPlane, float farPlane); 336 void updateScissor(const gl::State &glState); 337 void updateCullMode(const gl::State &glState); 338 void updateFrontFace(const gl::State &glState); 339 void updateDepthBias(const gl::State &glState); 340 void updateDrawFrameBufferBinding(const gl::Context *context); 341 void updateProgramExecutable(const gl::Context *context); 342 void updateVertexArray(const gl::Context *context); 343 344 angle::Result updateDefaultAttribute(size_t attribIndex); 345 angle::Result handleDirtyActiveTextures(const gl::Context *context); 346 angle::Result handleDirtyDefaultAttribs(const gl::Context *context); 347 angle::Result handleDirtyDriverUniforms(const gl::Context *context); 348 angle::Result handleDirtyDepthStencilState(const gl::Context *context); 349 angle::Result handleDirtyDepthBias(const gl::Context *context); 350 angle::Result checkIfPipelineChanged(const gl::Context *context, 351 gl::PrimitiveMode primitiveMode, 352 Optional<mtl::RenderPipelineDesc> *changedPipelineDesc); 353 354 // Dirty bits. 355 enum DirtyBitType : size_t 356 { 357 DIRTY_BIT_DEFAULT_ATTRIBS, 358 DIRTY_BIT_TEXTURES, 359 DIRTY_BIT_DRIVER_UNIFORMS, 360 DIRTY_BIT_DEPTH_STENCIL_DESC, 361 DIRTY_BIT_DEPTH_BIAS, 362 DIRTY_BIT_STENCIL_REF, 363 DIRTY_BIT_BLEND_COLOR, 364 DIRTY_BIT_VIEWPORT, 365 DIRTY_BIT_SCISSOR, 366 DIRTY_BIT_DRAW_FRAMEBUFFER, 367 DIRTY_BIT_CULL_MODE, 368 DIRTY_BIT_WINDING, 369 DIRTY_BIT_RENDER_PIPELINE, 370 DIRTY_BIT_MAX, 371 }; 372 373 // See compiler/translator/TranslatorVulkan.cpp: AddDriverUniformsToShader() 374 struct DriverUniforms 375 { 376 float viewport[4]; 377 378 float halfRenderAreaHeight; 379 float viewportYScale; 380 float negViewportYScale; 381 382 // NOTE(hqle): Transform feedsback is not supported yet. 383 uint32_t xfbActiveUnpaused; 384 uint32_t xfbVerticesPerDraw; 385 // NOTE: Explicit padding. Fill in with useful data when needed in the future. 386 int32_t padding[3]; 387 388 int32_t xfbBufferOffsets[4]; 389 uint32_t acbBufferOffsets[4]; 390 391 // We'll use x, y, z, w for near / far / diff / zscale respectively. 392 float depthRange[4]; 393 394 // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is 395 // padded to the size of two vec4's). 396 float preRotation[8]; 397 }; 398 399 struct DefaultAttribute 400 { 401 // NOTE(hqle): Support integer default attributes in ES 3.0 402 float values[4]; 403 }; 404 405 mtl::CommandBuffer mCmdBuffer; 406 mtl::RenderCommandEncoder mRenderEncoder; 407 mtl::BlitCommandEncoder mBlitEncoder; 408 mtl::ComputeCommandEncoder mComputeEncoder; 409 410 // Cached back-end objects 411 FramebufferMtl *mDrawFramebuffer = nullptr; 412 VertexArrayMtl *mVertexArray = nullptr; 413 ProgramMtl *mProgram = nullptr; 414 415 // Special flag to indicate current draw framebuffer is default framebuffer. 416 // We need this instead of calling mDrawFramebuffer->getState().isDefault() because 417 // mDrawFramebuffer might point to a deleted object, ContextMtl only knows about this very late, 418 // only during syncState() function call. 419 bool mDrawFramebufferIsDefault = true; 420 421 using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; 422 423 gl::AttributesMask mDirtyDefaultAttribsMask; 424 DirtyBits mDirtyBits; 425 426 // State 427 mtl::RenderPipelineDesc mRenderPipelineDesc; 428 mtl::DepthStencilDesc mDepthStencilDesc; 429 mtl::BlendDesc mBlendDesc; 430 MTLClearColor mClearColor; 431 uint32_t mClearStencil = 0; 432 uint32_t mStencilRefFront = 0; 433 uint32_t mStencilRefBack = 0; 434 MTLViewport mViewport; 435 MTLScissorRect mScissorRect; 436 MTLWinding mWinding; 437 MTLCullMode mCullMode; 438 bool mCullAllPolygons = false; 439 440 // Lineloop and TriFan index buffer 441 mtl::BufferPool mLineLoopIndexBuffer; 442 mtl::BufferPool mTriFanIndexBuffer; 443 // one buffer can be reused for any starting vertex in DrawArrays() 444 mtl::BufferRef mTriFanArraysIndexBuffer; 445 446 DriverUniforms mDriverUniforms; 447 448 DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs]; 449 }; 450 451 } // namespace rx 452 453 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */ 454