1// 2// Copyright (c) 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 7// DisplayMtl.mm: Metal implementation of DisplayImpl 8 9#include "libANGLE/renderer/metal/DisplayMtl.h" 10 11#include "libANGLE/Context.h" 12#include "libANGLE/Display.h" 13#include "libANGLE/Surface.h" 14#include "libANGLE/renderer/glslang_wrapper_utils.h" 15#include "libANGLE/renderer/metal/ContextMtl.h" 16#include "libANGLE/renderer/metal/SurfaceMtl.h" 17#include "libANGLE/renderer/metal/mtl_common.h" 18#include "libANGLE/renderer/metal/shaders/compiled/mtl_default_shaders.inc" 19#include "libANGLE/renderer/metal/shaders/mtl_default_shaders_src_autogen.inc" 20#include "platform/Platform.h" 21 22#include "EGL/eglext.h" 23 24namespace rx 25{ 26 27bool IsMetalDisplayAvailable() 28{ 29 // We only support macos 10.13+ and 11 for now. Since they are requirements for Metal 2.0. 30#if TARGET_OS_SIMULATOR 31 if (ANGLE_APPLE_AVAILABLE_XCI(10.13, 13.0, 13)) 32#else 33 if (ANGLE_APPLE_AVAILABLE_XCI(10.13, 13.0, 11)) 34#endif 35 { 36 return true; 37 } 38 return false; 39} 40 41DisplayImpl *CreateMetalDisplay(const egl::DisplayState &state) 42{ 43 return new DisplayMtl(state); 44} 45 46DisplayMtl::DisplayMtl(const egl::DisplayState &state) 47 : DisplayImpl(state), mUtils(this), mGlslangInitialized(false) 48{} 49 50DisplayMtl::~DisplayMtl() {} 51 52egl::Error DisplayMtl::initialize(egl::Display *display) 53{ 54 ASSERT(IsMetalDisplayAvailable()); 55 56 angle::Result result = initializeImpl(display); 57 if (result != angle::Result::Continue) 58 { 59 return egl::EglNotInitialized(); 60 } 61 return egl::NoError(); 62} 63 64angle::Result DisplayMtl::initializeImpl(egl::Display *display) 65{ 66 ANGLE_MTL_OBJC_SCOPE 67 { 68 mMetalDevice = [MTLCreateSystemDefaultDevice() ANGLE_MTL_AUTORELEASE]; 69 if (!mMetalDevice) 70 { 71 return angle::Result::Stop; 72 } 73 74 mCmdQueue.set([[mMetalDevice.get() newCommandQueue] ANGLE_MTL_AUTORELEASE]); 75 76 mCapsInitialized = false; 77 78 if (!mGlslangInitialized) 79 { 80 GlslangInitialize(); 81 mGlslangInitialized = true; 82 } 83 84 if (!mState.featuresAllDisabled) 85 { 86 initializeFeatures(); 87 } 88 89 ANGLE_TRY(mFormatTable.initialize(this)); 90 ANGLE_TRY(initializeShaderLibrary()); 91 92 return mUtils.initialize(); 93 } 94} 95 96void DisplayMtl::terminate() 97{ 98 mUtils.onDestroy(); 99 mCmdQueue.reset(); 100 mDefaultShaders = nil; 101 mMetalDevice = nil; 102 mCapsInitialized = false; 103 104 if (mGlslangInitialized) 105 { 106 GlslangRelease(); 107 mGlslangInitialized = false; 108 } 109} 110 111bool DisplayMtl::testDeviceLost() 112{ 113 return false; 114} 115 116egl::Error DisplayMtl::restoreLostDevice(const egl::Display *display) 117{ 118 return egl::NoError(); 119} 120 121std::string DisplayMtl::getVendorString() const 122{ 123 ANGLE_MTL_OBJC_SCOPE 124 { 125 std::string vendorString = "Google Inc."; 126 if (mMetalDevice) 127 { 128 vendorString += " Metal Renderer: "; 129 vendorString += mMetalDevice.get().name.UTF8String; 130 } 131 132 return vendorString; 133 } 134} 135 136DeviceImpl *DisplayMtl::createDevice() 137{ 138 UNIMPLEMENTED(); 139 return nullptr; 140} 141 142egl::Error DisplayMtl::waitClient(const gl::Context *context) 143{ 144 auto contextMtl = GetImplAs<ContextMtl>(context); 145 angle::Result result = contextMtl->finishCommandBuffer(); 146 147 if (result != angle::Result::Continue) 148 { 149 return egl::EglBadAccess(); 150 } 151 return egl::NoError(); 152} 153 154egl::Error DisplayMtl::waitNative(const gl::Context *context, EGLint engine) 155{ 156 UNIMPLEMENTED(); 157 return egl::EglBadAccess(); 158} 159 160SurfaceImpl *DisplayMtl::createWindowSurface(const egl::SurfaceState &state, 161 EGLNativeWindowType window, 162 const egl::AttributeMap &attribs) 163{ 164 return new SurfaceMtl(this, state, window, attribs); 165} 166 167SurfaceImpl *DisplayMtl::createPbufferSurface(const egl::SurfaceState &state, 168 const egl::AttributeMap &attribs) 169{ 170 UNIMPLEMENTED(); 171 return static_cast<SurfaceImpl *>(0); 172} 173 174SurfaceImpl *DisplayMtl::createPbufferFromClientBuffer(const egl::SurfaceState &state, 175 EGLenum buftype, 176 EGLClientBuffer clientBuffer, 177 const egl::AttributeMap &attribs) 178{ 179 UNIMPLEMENTED(); 180 return static_cast<SurfaceImpl *>(0); 181} 182 183SurfaceImpl *DisplayMtl::createPixmapSurface(const egl::SurfaceState &state, 184 NativePixmapType nativePixmap, 185 const egl::AttributeMap &attribs) 186{ 187 UNIMPLEMENTED(); 188 return static_cast<SurfaceImpl *>(0); 189} 190 191ImageImpl *DisplayMtl::createImage(const egl::ImageState &state, 192 const gl::Context *context, 193 EGLenum target, 194 const egl::AttributeMap &attribs) 195{ 196 UNIMPLEMENTED(); 197 return nullptr; 198} 199 200rx::ContextImpl *DisplayMtl::createContext(const gl::State &state, 201 gl::ErrorSet *errorSet, 202 const egl::Config *configuration, 203 const gl::Context *shareContext, 204 const egl::AttributeMap &attribs) 205{ 206 return new ContextMtl(state, errorSet, this); 207} 208 209StreamProducerImpl *DisplayMtl::createStreamProducerD3DTexture( 210 egl::Stream::ConsumerType consumerType, 211 const egl::AttributeMap &attribs) 212{ 213 UNIMPLEMENTED(); 214 return nullptr; 215} 216 217ShareGroupImpl *DisplayMtl::createShareGroup() 218{ 219 return new ShareGroupMtl(); 220} 221 222gl::Version DisplayMtl::getMaxSupportedESVersion() const 223{ 224 return mtl::kMaxSupportedGLVersion; 225} 226 227gl::Version DisplayMtl::getMaxConformantESVersion() const 228{ 229 return std::min(getMaxSupportedESVersion(), gl::Version(2, 0)); 230} 231 232EGLSyncImpl *DisplayMtl::createSync(const egl::AttributeMap &attribs) 233{ 234 UNIMPLEMENTED(); 235 return nullptr; 236} 237 238egl::Error DisplayMtl::makeCurrent(egl::Surface *drawSurface, 239 egl::Surface *readSurface, 240 gl::Context *context) 241{ 242 if (!context) 243 { 244 return egl::NoError(); 245 } 246 247 return egl::NoError(); 248} 249 250void DisplayMtl::generateExtensions(egl::DisplayExtensions *outExtensions) const 251{ 252 outExtensions->flexibleSurfaceCompatibility = true; 253} 254 255void DisplayMtl::generateCaps(egl::Caps *outCaps) const {} 256 257void DisplayMtl::populateFeatureList(angle::FeatureList *features) {} 258 259egl::ConfigSet DisplayMtl::generateConfigs() 260{ 261 // NOTE(hqle): generate more config permutations 262 egl::ConfigSet configs; 263 264 const gl::Version &maxVersion = getMaxSupportedESVersion(); 265 ASSERT(maxVersion >= gl::Version(2, 0)); 266 bool supportsES3 = maxVersion >= gl::Version(3, 0); 267 268 egl::Config config; 269 270 // Native stuff 271 config.nativeVisualID = 0; 272 config.nativeVisualType = 0; 273 config.nativeRenderable = EGL_TRUE; 274 275 config.colorBufferType = EGL_RGB_BUFFER; 276 config.luminanceSize = 0; 277 config.alphaMaskSize = 0; 278 279 config.transparentType = EGL_NONE; 280 281 // Pbuffer 282 config.maxPBufferWidth = 4096; 283 config.maxPBufferHeight = 4096; 284 config.maxPBufferPixels = 4096 * 4096; 285 286 // Caveat 287 config.configCaveat = EGL_NONE; 288 289 // Misc 290 config.sampleBuffers = 0; 291 config.samples = 0; 292 config.level = 0; 293 config.bindToTextureRGB = EGL_FALSE; 294 config.bindToTextureRGBA = EGL_FALSE; 295 296 config.surfaceType = EGL_WINDOW_BIT; 297 298 config.minSwapInterval = 1; 299 config.maxSwapInterval = 1; 300 301 config.renderTargetFormat = GL_RGBA8; 302 config.depthStencilFormat = GL_DEPTH24_STENCIL8; 303 304 config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); 305 config.renderableType = config.conformant; 306 307 config.matchNativePixmap = EGL_NONE; 308 309 config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; 310 311 // Buffer sizes 312 config.redSize = 8; 313 config.greenSize = 8; 314 config.blueSize = 8; 315 config.alphaSize = 8; 316 config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize; 317 318 // With DS 319 config.depthSize = 24; 320 config.stencilSize = 8; 321 configs.add(config); 322 323 // With D 324 config.depthSize = 24; 325 config.stencilSize = 0; 326 configs.add(config); 327 328 // With S 329 config.depthSize = 0; 330 config.stencilSize = 8; 331 configs.add(config); 332 333 // No DS 334 config.depthSize = 0; 335 config.stencilSize = 0; 336 configs.add(config); 337 338 return configs; 339} 340 341bool DisplayMtl::isValidNativeWindow(EGLNativeWindowType window) const 342{ 343 NSObject *layer = (__bridge NSObject *)(window); 344 return [layer isKindOfClass:[CALayer class]]; 345} 346 347std::string DisplayMtl::getRendererDescription() const 348{ 349 ANGLE_MTL_OBJC_SCOPE 350 { 351 std::string desc = "Metal Renderer"; 352 353 if (mMetalDevice) 354 { 355 desc += ": "; 356 desc += mMetalDevice.get().name.UTF8String; 357 } 358 359 return desc; 360 } 361} 362 363gl::Caps DisplayMtl::getNativeCaps() const 364{ 365 ensureCapsInitialized(); 366 return mNativeCaps; 367} 368const gl::TextureCapsMap &DisplayMtl::getNativeTextureCaps() const 369{ 370 ensureCapsInitialized(); 371 return mNativeTextureCaps; 372} 373const gl::Extensions &DisplayMtl::getNativeExtensions() const 374{ 375 ensureCapsInitialized(); 376 return mNativeExtensions; 377} 378 379void DisplayMtl::ensureCapsInitialized() const 380{ 381 if (mCapsInitialized) 382 { 383 return; 384 } 385 386 mCapsInitialized = true; 387 388 // Reset 389 mNativeCaps = gl::Caps(); 390 391 // Fill extension and texture caps 392 initializeExtensions(); 393 initializeTextureCaps(); 394 395 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 396 mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1; 397 mNativeCaps.max3DTextureSize = 2048; 398#if TARGET_OS_OSX || TARGET_OS_MACCATALYST 399 mNativeCaps.max2DTextureSize = 16384; 400 mNativeCaps.maxVaryingVectors = 31; 401 mNativeCaps.maxVertexOutputComponents = 124; 402#else 403 if ([getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) 404 { 405 mNativeCaps.max2DTextureSize = 16384; 406 mNativeCaps.maxVertexOutputComponents = 124; 407 mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4; 408 } 409 else 410 { 411 mNativeCaps.max2DTextureSize = 8192; 412 mNativeCaps.maxVertexOutputComponents = 60; 413 mNativeCaps.maxVaryingVectors = mNativeCaps.maxVertexOutputComponents / 4; 414 } 415#endif 416 417 mNativeCaps.maxArrayTextureLayers = 2048; 418 mNativeCaps.maxLODBias = 0; 419 mNativeCaps.maxCubeMapTextureSize = mNativeCaps.max2DTextureSize; 420 mNativeCaps.maxRenderbufferSize = mNativeCaps.max2DTextureSize; 421 mNativeCaps.minAliasedPointSize = 1; 422 mNativeCaps.maxAliasedPointSize = 511; 423 424 mNativeCaps.minAliasedLineWidth = 1.0f; 425 mNativeCaps.maxAliasedLineWidth = 1.0f; 426 427 mNativeCaps.maxDrawBuffers = mtl::kMaxRenderTargets; 428 mNativeCaps.maxFramebufferWidth = mNativeCaps.max2DTextureSize; 429 mNativeCaps.maxFramebufferHeight = mNativeCaps.max2DTextureSize; 430 mNativeCaps.maxColorAttachments = mtl::kMaxRenderTargets; 431 mNativeCaps.maxViewportWidth = mNativeCaps.max2DTextureSize; 432 mNativeCaps.maxViewportHeight = mNativeCaps.max2DTextureSize; 433 434 // NOTE(hqle): MSAA 435 mNativeCaps.maxSampleMaskWords = 0; 436 mNativeCaps.maxColorTextureSamples = 1; 437 mNativeCaps.maxDepthTextureSamples = 1; 438 mNativeCaps.maxIntegerSamples = 1; 439 440 mNativeCaps.maxVertexAttributes = mtl::kMaxVertexAttribs; 441 mNativeCaps.maxVertexAttribBindings = mtl::kMaxVertexAttribs; 442 mNativeCaps.maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max(); 443 mNativeCaps.maxVertexAttribStride = std::numeric_limits<GLint>::max(); 444 445 mNativeCaps.maxElementsIndices = std::numeric_limits<GLuint>::max(); 446 mNativeCaps.maxElementsVertices = std::numeric_limits<GLuint>::max(); 447 448 // Looks like all floats are IEEE according to the docs here: 449 mNativeCaps.vertexHighpFloat.setIEEEFloat(); 450 mNativeCaps.vertexMediumpFloat.setIEEEFloat(); 451 mNativeCaps.vertexLowpFloat.setIEEEFloat(); 452 mNativeCaps.fragmentHighpFloat.setIEEEFloat(); 453 mNativeCaps.fragmentMediumpFloat.setIEEEFloat(); 454 mNativeCaps.fragmentLowpFloat.setIEEEFloat(); 455 456 mNativeCaps.vertexHighpInt.setTwosComplementInt(32); 457 mNativeCaps.vertexMediumpInt.setTwosComplementInt(32); 458 mNativeCaps.vertexLowpInt.setTwosComplementInt(32); 459 mNativeCaps.fragmentHighpInt.setTwosComplementInt(32); 460 mNativeCaps.fragmentMediumpInt.setTwosComplementInt(32); 461 mNativeCaps.fragmentLowpInt.setTwosComplementInt(32); 462 463 GLuint maxUniformVectors = mtl::kDefaultUniformsMaxSize / (sizeof(GLfloat) * 4); 464 465 const GLuint maxUniformComponents = maxUniformVectors * 4; 466 467 // Uniforms are implemented using a uniform buffer, so the max number of uniforms we can 468 // support is the max buffer range divided by the size of a single uniform (4X float). 469 mNativeCaps.maxVertexUniformVectors = maxUniformVectors; 470 mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Vertex] = maxUniformComponents; 471 mNativeCaps.maxFragmentUniformVectors = maxUniformVectors; 472 mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents; 473 474 // NOTE(hqle): support UBO (ES 3.0 feature) 475 mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Vertex] = 0; 476 mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Fragment] = 0; 477 mNativeCaps.maxCombinedUniformBlocks = 0; 478 479 // Note that we currently implement textures as combined image+samplers, so the limit is 480 // the minimum of supported samplers and sampled images. 481 mNativeCaps.maxCombinedTextureImageUnits = mtl::kMaxGLSamplerBindings; 482 mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = mtl::kMaxShaderSamplers; 483 mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex] = mtl::kMaxShaderSamplers; 484 485 // NOTE(hqle): support storage buffer. 486 const uint32_t maxPerStageStorageBuffers = 0; 487 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] = maxPerStageStorageBuffers; 488 mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] = maxPerStageStorageBuffers; 489 mNativeCaps.maxCombinedShaderStorageBlocks = maxPerStageStorageBuffers; 490 491 // Fill in additional limits for UBOs and SSBOs. 492 mNativeCaps.maxUniformBufferBindings = 0; 493 mNativeCaps.maxUniformBlockSize = 0; 494 mNativeCaps.uniformBufferOffsetAlignment = 0; 495 496 mNativeCaps.maxShaderStorageBufferBindings = 0; 497 mNativeCaps.maxShaderStorageBlockSize = 0; 498 mNativeCaps.shaderStorageBufferOffsetAlignment = 0; 499 500 // NOTE(hqle): support UBO 501 for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes) 502 { 503 mNativeCaps.maxCombinedShaderUniformComponents[shaderType] = maxUniformComponents; 504 } 505 506 mNativeCaps.maxCombinedShaderOutputResources = 0; 507 508 mNativeCaps.maxTransformFeedbackInterleavedComponents = 509 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; 510 mNativeCaps.maxTransformFeedbackSeparateAttributes = 511 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; 512 mNativeCaps.maxTransformFeedbackSeparateComponents = 513 gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS; 514 515 // NOTE(hqle): support MSAA. 516 mNativeCaps.maxSamples = 1; 517 518 // GL_APPLE_clip_distance 519 mNativeCaps.maxClipDistances = 8; 520} 521 522void DisplayMtl::initializeExtensions() const 523{ 524 // Reset 525 mNativeExtensions = gl::Extensions(); 526 527 // Enable this for simple buffer readback testing, but some functionality is missing. 528 // NOTE(hqle): Support full mapBufferRange extension. 529 mNativeExtensions.mapBufferOES = true; 530 mNativeExtensions.mapBufferRange = false; 531 mNativeExtensions.textureStorage = true; 532 mNativeExtensions.drawBuffers = false; 533 mNativeExtensions.fragDepth = true; 534 mNativeExtensions.framebufferBlit = false; 535 mNativeExtensions.framebufferMultisample = false; 536 mNativeExtensions.copyTexture = false; 537 mNativeExtensions.copyCompressedTexture = false; 538 mNativeExtensions.debugMarker = false; 539 mNativeExtensions.robustness = true; 540 mNativeExtensions.textureBorderClampOES = false; // not implemented yet 541 mNativeExtensions.translatedShaderSource = true; 542 mNativeExtensions.discardFramebuffer = true; 543 544 // Enable EXT_blend_minmax 545 mNativeExtensions.blendMinMax = true; 546 547 mNativeExtensions.eglImageOES = false; 548 mNativeExtensions.eglImageExternalOES = false; 549 // NOTE(hqle): Support GL_OES_EGL_image_external_essl3. 550 mNativeExtensions.eglImageExternalEssl3OES = false; 551 552 mNativeExtensions.memoryObject = false; 553 mNativeExtensions.memoryObjectFd = false; 554 555 mNativeExtensions.semaphore = false; 556 mNativeExtensions.semaphoreFd = false; 557 558 mNativeExtensions.instancedArraysANGLE = mFeatures.hasBaseVertexInstancedDraw.enabled; 559 mNativeExtensions.instancedArraysEXT = mNativeExtensions.instancedArraysANGLE; 560 561 mNativeExtensions.robustBufferAccessBehavior = false; 562 563 mNativeExtensions.eglSyncOES = false; 564 565 // NOTE(hqle): support occlusion query 566 mNativeExtensions.occlusionQueryBoolean = false; 567 568 mNativeExtensions.disjointTimerQuery = false; 569 mNativeExtensions.queryCounterBitsTimeElapsed = false; 570 mNativeExtensions.queryCounterBitsTimestamp = false; 571 572 mNativeExtensions.textureFilterAnisotropic = true; 573 mNativeExtensions.maxTextureAnisotropy = 16; 574 575 // NOTE(hqle): Support true NPOT textures. 576 mNativeExtensions.textureNPOTOES = false; 577 578 mNativeExtensions.texture3DOES = false; 579 580 mNativeExtensions.standardDerivativesOES = true; 581 582 mNativeExtensions.elementIndexUintOES = true; 583 584 // GL_APPLE_clip_distance 585 mNativeExtensions.clipDistanceAPPLE = true; 586} 587 588void DisplayMtl::initializeTextureCaps() const 589{ 590 mNativeTextureCaps.clear(); 591 592 mFormatTable.generateTextureCaps(this, &mNativeTextureCaps, 593 &mNativeCaps.compressedTextureFormats); 594 595 // Re-verify texture extensions. 596 mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps); 597 598 // Disable all depth buffer and stencil buffer readback extensions until we need them 599 mNativeExtensions.readDepthNV = false; 600 mNativeExtensions.readStencilNV = false; 601 mNativeExtensions.depthBufferFloat2NV = false; 602} 603 604void DisplayMtl::initializeFeatures() 605{ 606 // default values: 607 mFeatures.hasBaseVertexInstancedDraw.enabled = true; 608 mFeatures.hasDepthTextureFiltering.enabled = false; 609 mFeatures.hasNonUniformDispatch.enabled = true; 610 mFeatures.hasTextureSwizzle.enabled = false; 611 mFeatures.allowSeparatedDepthStencilBuffers.enabled = false; 612 613#if TARGET_OS_OSX || TARGET_OS_MACCATALYST 614 mFeatures.hasDepthTextureFiltering.enabled = true; 615 616 // Texture swizzle is only supported if macos sdk 10.15 is present 617# if defined(__MAC_10_15) 618 if (ANGLE_APPLE_AVAILABLE_XC(10.15, 13.0)) 619 { 620 // The runtime OS must be MacOS 10.15+ or Mac Catalyst for this to be supported: 621 ANGLE_FEATURE_CONDITION((&mFeatures), hasTextureSwizzle, 622 [getMetalDevice() supportsFamily:MTLGPUFamilyMac2]); 623 } 624# endif 625#elif TARGET_OS_IOS 626 // Base Vertex drawing is only supported since GPU family 3. 627 ANGLE_FEATURE_CONDITION((&mFeatures), hasBaseVertexInstancedDraw, 628 [getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]); 629 630 ANGLE_FEATURE_CONDITION((&mFeatures), hasNonUniformDispatch, 631 [getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]); 632 633# if !TARGET_OS_SIMULATOR 634 mFeatures.allowSeparatedDepthStencilBuffers.enabled = true; 635# endif 636#endif 637 638 angle::PlatformMethods *platform = ANGLEPlatformCurrent(); 639 platform->overrideFeaturesMtl(platform, &mFeatures); 640} 641 642angle::Result DisplayMtl::initializeShaderLibrary() 643{ 644 mtl::AutoObjCObj<NSError> err = nil; 645 646#if defined(ANGLE_MTL_DEBUG_INTERNAL_SHADERS) 647 mDefaultShaders = CreateShaderLibrary(getMetalDevice(), default_metallib_src, 648 sizeof(default_metallib_src), &err); 649#else 650 mDefaultShaders = CreateShaderLibraryFromBinary(getMetalDevice(), compiled_default_metallib, 651 compiled_default_metallib_len, &err); 652#endif 653 654 if (err && !mDefaultShaders) 655 { 656 ANGLE_MTL_OBJC_SCOPE 657 { 658 ERR() << "Internal error: " << err.get().localizedDescription.UTF8String; 659 } 660 return angle::Result::Stop; 661 } 662 663 return angle::Result::Continue; 664} 665 666} // namespace rx 667